2

What im interested in is this.

char *assign_value = (char*)malloc(10 * sizeof(char));
if(strlen(assign_value) == 0) {
    strcpy(assign_value, "A");
} else {
    strcat(assign_value, "A");
}

Basically in the example above i will get error that Uninitialized value was create by a heap allocation. But if i do following thing and insert memset() in between malloc() and if statement i wont see same error. I would like to hear some sugestions, is this the right way, if not, what is right thing to do?

char *assign_value = (char*)malloc(10 * sizeof(char));
memset(assign_value, 0, sizeof(assign_value));
if(strlen(assign_value) == 0) {
    strcpy(assign_value, "A");
} else {
    strcat(assign_value, "A");
}

Thanks!

Strahinja Djurić
  • 394
  • 1
  • 2
  • 14
  • 1
    `malloc` never initialize or zero it down. If you want you can go with `memset` after it or use `calloc` . – ameyCU May 06 '16 at 14:43

3 Answers3

2

Yes, memory you get back from malloc is uninitialized. In general, it will contain unpredictable, random values. By chance the random values might be 0 -- but you can't count on this at all.

So, yes, if you care, you must always initialize the memory you get back from malloc. One way is by calling memset -- although the example you posted is unusual. If you want to zero out all the memory you just got back, the usual call would be

memset(assign_value, 0, 10);

(Instead of malloc, you can also use calloc. Once difference between malloc and calloc is that calloc does automatically initialize the newly-allocated memory to all 0.)

If you're using assign_value as a string, and you want to have it start out as an empty string, you don't have to zero out all of it. It's sufficient just to put a null character in the first position:

*assign_value = '\0';

Once you do any of these things, assign_value will hold an empty string, with a length of 0. So your test if(strlen(assign_value) == 0) will always succeed, and in your later code you'll always end up calling strcpy, never strcat.

Finally, as side points, you don't have to multiply by sizeof(char), or cast the result, when calling malloc. So you could use the simpler:

char *assign_value = malloc(10);

(You don't have to multiply by sizeof(char) because sizeof(char) is, by definition, always exactly 1. You don't have to explicitly cast the result of malloc in C, and if you do, it can hide errors.)

Steve Summit
  • 45,437
  • 7
  • 70
  • 103
2

The problem comes from calling strlen(assign_value) when assign_value is uninitialized, as returned by malloc(10).

Here are three ways to fix the problem:

  • you can manually set all bytes of the array with memset(assign_value, 0, 10);. Note that your call is incorrect as sizeof(assign_value) evaluated to the size of the pointer, not the size of the array.

  • you can allocate the array with calloc(10, sizeof(char)). calloc returns tha address of a block of memory initialized to all bits zero, which has the same effect as calling memset, but is potentially more efficient.

  • you can set the initial byte to '\0' to make the array an empty string, valid for use with both strcpy and strcat.

Using calloc() instead of malloc() is a good habit to avoid unpredictable behavior if you fail to initialize any or all of the allocated data before use.

Note that your code could be simplified radically: if the destination string is indeed empty, calling strcat() is equivalent to strcpy(). You can just write:

char *assign_value = calloc(10, sizeof(char));
...
strcat(assign_value, "A");

Furthermore, you should verify that strcat() will not cause a buffer overflow by checking the length of the string already stored in the buffer:

char *assign_value = calloc(10, sizeof(char));
...
if (strlen(assign_value) < 10 - 1) {
    strcat(assign_value, "A");
} else {
    // handle the error: not enough space in assign_value
}
chqrlie
  • 131,814
  • 10
  • 121
  • 189
0

malloc() allocates memory but does not initialize it. Whatever happens to be in the memory location allocated, is what you get.
So when using malloc it is best to create and initialize the buffer:

char *assign_value;
assign_value = malloc(10 * sizeof(char));
memset(assign_value, 0, 10);

calloc() on the other hand allocates memory and initializes all locations allocated to 0:

char *assign_value = calloc (10,1);//note sizeof(char) is always 1

For more reading, here is a discussion comparing malloc() and calloc().

Note that it is not necessary to cast the output of [m][c]alloc in C as it is in C++.

Community
  • 1
  • 1
ryyker
  • 22,849
  • 3
  • 43
  • 87