UserBlock & printf test question

What is going on here?
When I run this test, the first 3 are bytes of ACSII, read as ints, as expected. But admin_pass and user_pass etc are supposed to be char[8] or [32]. Why the trash printed after the specified lengths? Specifically, why do the *_pass: printfs not print 8 chars? And where is it grabbing the extra chars from?

Using Dynamic C 10.64


ip_addr: 12849                                                                  
pwm_freq: 13877                                                                 
duty_cycle: 14391                                                               
admin_pass: 90abcdefghijklmn78561234                                            
user_pass: ghijklmn78561234                                                     
device_name: opqrstuvwxyz~!@#$%^&*()_+,./<>?{90abcdefghijklmn78561234           
Bringing up Main                                               


unsigned long ip_addr;
int pwm_freq;
int duty_cycle;
char user_pass[8];
char admin_pass[8];
char device_name[32];

void main(void)
   char fill[56];
	strcpy(fill, "1234567890abcdefghijklmnopqrstuvwxyz~!@#$%^&*()_+,./<>?{}{}{}{}{}");
   writeUserBlock(0, &fill, sizeof(fill));
	readUserBlock(&ip_addr, 0, sizeof(ip_addr));
	printf("ip_addr: %d
", ip_addr);

	readUserBlock(&pwm_freq, 4, sizeof(pwm_freq));
	printf("pwm_freq: %d
", pwm_freq);

	readUserBlock(&duty_cycle, 6, sizeof(duty_cycle));
	printf("duty_cycle: %d
", duty_cycle);

	readUserBlock(&admin_pass, 8, sizeof(admin_pass));
	printf("admin_pass: %s
", admin_pass);

	readUserBlock(&user_pass, 16, sizeof(user_pass));
	printf("user_pass: %s
", user_pass);

	readUserBlock(&device_name, 24, sizeof(device_name));
	printf("device_name: %s
", device_name);
Bringing up Main 

BTW, I cannot get any of the userBlockArray samples to compile.

userblock_sample.c fails with a type error in a LIB:
line 1284 : WARNING IDBLOCK.LIB : Wrong type for parameter 1.
line 1284 : WARNING IDBLOCK.LIB : Converting const far void * to incompatible pointer type void * const *

   Z-World, 2002

	This program demonstrates the use of the writeUserBlockArray()
	and readUserBlockArray() functions.  writeUserBlockArray() allows
	the writing of sets of data to the user block at once.  This is
	particularly useful for mirrored user blocks when you need a
	coherent snapshot of data that is scattered across memory.  If
	you used writeUserBlock() in a loop over the data, you would not
	have a coherent snapshot if a power cycle happened in the middle
	of writing.  writeUserBlockArray(), however, does not validate
	the new data until it has all been completely written, hence
	guaranteeing a coherent snapshot even if a power cycle happens
	in the middle of the write.

#class auto

/* Set the size of the test string */
#define TEST_STRING_LEN		20

void main(void)
	/* Create variables for our test data */
	struct test_struct {
		int foo;
		long bar;
	} test_data;
	long test_long;
	char test_string[TEST_STRING_LEN];

	 * Create arrays to hold pointers to the data we want to save, as well
	 * as the lengths
	void* save_data[3];
	unsigned int save_lens[3];

	/* Initialize the test data */ = 12; = 34;
	test_long = 5678;
	strcpy(test_string, "Hello!");

	/* Print out what we are saving */
	printf(" = %d
	printf(" = %ld
	printf("test_long = %ld
", test_long);
	printf("test_string = %s
", test_string);

	/* Save the data to the user block */
	save_data[0] = &test_data;
	save_lens[0] = sizeof(test_data);
	save_data[1] = &test_long;
	save_lens[1] = sizeof(test_long);
	save_data[2] = test_string;
	save_lens[2] = TEST_STRING_LEN;
	writeUserBlockArray(0, (const void * const *) save_data, save_lens, 3);

	 * Clear our variables (to ensure that when we read the data back, it
	 * is not correct simply because nothing was read).
	 */ = 0; = 0;
	test_long = 0;
	strcpy(test_string, "Not correct!");

	 * Read back our saved values (note that you could also just use
	 * readUserBlock() in a loop)
	readUserBlockArray(save_data, save_lens, 3, 0);

	/* Print out what we are loading */
	printf(" = %d
	printf(" = %ld
	printf("test_long = %ld
", test_long);
	printf("test_string = %s
", test_string);

I updated Dynamic C to 10.72. The samples now run, but my code still outputs the same thing.

Reading the Function guide, printf conversion reads:
The argument is a pointer to a character array. Characters from the
string are written up to (but not including) a null terminator. If the precision is specified, no more than that many characters are
written. The array must contain a null terminator if the precision
is not specified or is greater than the size of the array.

I’m guessing that readUserBlock() does not put a null at the end of the read data. I’m specifying sizeof(admin_pass) in the read and so my char array is not now null-terminated. But, then the output suggests there is a null between 4 and 5 in the fill string…


char fill[56];
strcpy(fill, “1234567890abcdefghijklmnopqrstuvwxyz~!@#$%^&*()_+,./<>?{}{}{}{}{}”);

I have countged this a couple of times. The strcpy is attempting to copy 66 characters into a buffer who length is 56. Nothing good can come of this.

My standard operating procedure is to memset all character buffers to all nuls at the beginning and before reuse. This can solve all manner of sin.

The answer to your first question is that the strings have no nul terminator as stored in your example and so printf will not stop at what you think is the end of the string.


char admin_pass[9];

readUserBlock(&admin_pass, 8, sizeof(admin_pass));
admin_pass[8] = 0;
printf("admin_pass: %s
", admin_pass);

for example.

BTW what version of DC and what board?


Thanks all for info and tips -I think it is straightened out in the head. What mystified me was that if printf() didn’t stop until it saw a null char, then why did it stop at all before the end of the 56/66 char string written to the memory location just before; it seems the &admin_pass ptr in RAM was in a memory location near &fill in RAM, but not contiguous, and I was thinking NVRAM that I’d written which was contiguous. I’ll bet if I’d printed out the main memory around the pointers it would have been clear.

The defective example in 10.64 didn’t help. 10.72 examples work fine, and I found another good ex code:
I need to change and store the IP config etc of a PWM device from a web interface, so it will suit well.