Appending Char array to Char pointer - c

I have been on this fow quite some time now and i dont seem to figure it out.
I have this code:
unsigned char *src;
int length = (parameterArray[i].sizeInBits/8) + 1; // check how long array should be
unsigned char tmp[length]; // declare array
memcpy(tmp, (char*)&parameterArray[i].valueU8, length); // in this case copy char to array
src = realloc(src, strlen(src) + strlen(tmp)); // reallocate space for total string
strncat(src, tmp, strlen(tmp)); // merge
every time the code crashes on the reallocating part.
I have tried almost everything and nothing works. Please help

src is an unitialized pointer, and will hold a random memory address. The preconditions for realloc() state. from the linked reference page:
Reallocates the given area of memory. It must be previously allocated by malloc(), calloc() or realloc() and not yet freed with free(), otherwise, the results are undefined.
When using realloc() store the result to a temporary variable to avoid a memory leak in the event of failure.
Additionally, calling strlen() on src will also result in undefined behaviour. As first pointed out by mani tmp must be null terminated in order for strlen() and strcpy() to work correctly. The space calculated in the realloc() must be increased by one to allocate an additional char for the terminating null character.
Example code fix:
unsigned char tmp[length + 1];
memcpy(tmp, parameterArray[i].valueU8, length);
tmp[length] = 0;
unsigned char* src = NULL;
unsigned char* src_tmp = realloc(src, (src ? strlen(src) : 0) + strlen(tmp) + 1);
if (src_tmp)
{
if (!src) *src_tmp = 0; /* Ensure null character present before strcat(). */
src = src_tmp;
strcat(src, tmp);
}

As per your code of this line memcpy(tmp, (char*)&parameterArray[i].valueU8, length); you are trying to copy valueU8 which must be assigned with Null terminator. Otherwise it will crash in this line src = realloc(src, strlen(src) + strlen(tmp));

From man pages of realloc
Unless ptr is NULL, it must have been returned by an earlier call to malloc(), calloc() or realloc().
and your src is an uninitialized pointer

Related

Reallocating memory to 2D array element is not working C Language; [duplicate]

Can someone explain to me why my call to malloc with a string size of 6 returns a sizeof of 4 bytes? In fact, any integer argument I give malloc I get a sizeof of 4. Next, I am trying to copy two strings. Why is my ouput of the copied string (NULL)?
Following is my code:
int main()
{
char * str = "string";
char * copy = malloc(sizeof(str) + 1);
printf("bytes allocated for copy: %d\n", sizeof(copy));
while(*str != '\0'){
*copy = *str;
str++;
copy++;
}
copy = '\0';
printf("%s\n", copy);
}
sizeof(str) returns the size of a pointer of type char*. What you should do is to malloc the size of the string it self:
char * copy = malloc(strlen(str) + 1);
Also, these lines:
while(*str != '\0'){
*copy = *str;
str++;
copy++;
}
copy = '\0';
Can be rewritten easily in C like this:
while(*copy++ = *str++);
First you should understand that sizeof(xxx) where xxx is any left value expression (a variable) is always equivalent to do sizeof(type of xxx). Hence what is really doing your sizeof(str) is returning the size of a char *, that is the size of any other pointer. On a 32 bits architecture you'll get 4, on a 64 bits architecture it'll be 8, etc.
So, as others also explained you have to know the length of the string you want to allocate, and then add 1 to store the terminal \0, C implicitly use to put at the end of strings.
But to do what you want (copy a string and allocate necessary space) it will be more simple and more efficient to use strdup, that does exactly that : a malloc and a strcopy.
You should also not forget to free space you allocated yourself (using malloc, calloc, strdup or any other allocation function). In C it won't go away when allocated variable go out of scope. It will stay used until the end of the program. That's what you call a memory leak.
#include <string.h> /* for strdup, strlen */
#include <stdio.h> /* for printf */
int main()
{
char * str = "string";
char * copy = strdup(str);
printf("bytes at least allocated for copy: %d\n", strlen(copy)+1);
printf("%s\n", copy);
free(copy);
}
One last point : I changed message to bytes at least allocated because you don't really know the size allocated when calling malloc. It quite often allocates a slighly more space that what you asked for. One reason is that in many memory managers free blocks are linked together using some hidden data structure and any allocated block should be able to contain at least such structure, another is that allocated blocks are always aligned in such a way to be compatible with any type alignment.
Hope it will help you to understand C a little better.
You're getting the size of the str pointer (4 bytes), not what it's pointing to?
sizeof(str) returns the space necessary to store the pointer to the string, not the string itself. You can see the size of the string with strlen(str) for example.
Then you affect your copy pointer to an integer which has the value 0 (the character '\0'). It is the same as copy = NULL, which is what the printf() function shows you.
sizeof() returns the size of the actual type of the variable. So, when you define your type as char *, it returns the size of a pointer.
But if you made your variable an array, sizeof would return the size of the array itself, which would do what you want to do:
char *ptr = "moo to you";
char arr[] = "moo to you";
assert(sizeof(ptr) == 4); // assuming 32 bit
assert(sizeof(arr) == 11); // sizeof array includes terminating NUL
assert(strlen(arr) == 10); // strlen does not include terminating NUL
To tackle your second questions, by executing the statement copy++ you have changed the value of copy (that is, the address in memory that holds a char array) so that by the time you print it out, it is pointing at the end of the array rather than the beginning (the value returned by malloc()). You will need an extra variable to update the string and be able to access the beginning of the string:
Edit to repair malloc/sizeof issue - thanks CL.
char * str = "string";
/* char * copy = malloc(sizeof(str) + 1); Oops */
char * copy = malloc(strlen(str) + 1);
char * original_copy = copy;
printf("bytes allocated for copy: %d\n", sizeof(copy));
while(*str != '\0'){
*copy = *str;
str++;
copy++;
}
copy = '\0';
printf("%s\n", original_copy);
sizeof() returns you the size of the pointer and not the amount of allocated bytes. You don't need to count the allocated bytes, just check if the returned pointer is not NULL.
The line copy = '\0'; resets the pointer and makes it NULL.
You can use:
size_t malloc_usable_size (void *ptr);
instead of : sizeof
But it returns the real size of the allocated memory block! Not the size you passed to malloc!

sizeof Calloc producing wrong output [duplicate]

Can someone explain to me why my call to malloc with a string size of 6 returns a sizeof of 4 bytes? In fact, any integer argument I give malloc I get a sizeof of 4. Next, I am trying to copy two strings. Why is my ouput of the copied string (NULL)?
Following is my code:
int main()
{
char * str = "string";
char * copy = malloc(sizeof(str) + 1);
printf("bytes allocated for copy: %d\n", sizeof(copy));
while(*str != '\0'){
*copy = *str;
str++;
copy++;
}
copy = '\0';
printf("%s\n", copy);
}
sizeof(str) returns the size of a pointer of type char*. What you should do is to malloc the size of the string it self:
char * copy = malloc(strlen(str) + 1);
Also, these lines:
while(*str != '\0'){
*copy = *str;
str++;
copy++;
}
copy = '\0';
Can be rewritten easily in C like this:
while(*copy++ = *str++);
First you should understand that sizeof(xxx) where xxx is any left value expression (a variable) is always equivalent to do sizeof(type of xxx). Hence what is really doing your sizeof(str) is returning the size of a char *, that is the size of any other pointer. On a 32 bits architecture you'll get 4, on a 64 bits architecture it'll be 8, etc.
So, as others also explained you have to know the length of the string you want to allocate, and then add 1 to store the terminal \0, C implicitly use to put at the end of strings.
But to do what you want (copy a string and allocate necessary space) it will be more simple and more efficient to use strdup, that does exactly that : a malloc and a strcopy.
You should also not forget to free space you allocated yourself (using malloc, calloc, strdup or any other allocation function). In C it won't go away when allocated variable go out of scope. It will stay used until the end of the program. That's what you call a memory leak.
#include <string.h> /* for strdup, strlen */
#include <stdio.h> /* for printf */
int main()
{
char * str = "string";
char * copy = strdup(str);
printf("bytes at least allocated for copy: %d\n", strlen(copy)+1);
printf("%s\n", copy);
free(copy);
}
One last point : I changed message to bytes at least allocated because you don't really know the size allocated when calling malloc. It quite often allocates a slighly more space that what you asked for. One reason is that in many memory managers free blocks are linked together using some hidden data structure and any allocated block should be able to contain at least such structure, another is that allocated blocks are always aligned in such a way to be compatible with any type alignment.
Hope it will help you to understand C a little better.
You're getting the size of the str pointer (4 bytes), not what it's pointing to?
sizeof(str) returns the space necessary to store the pointer to the string, not the string itself. You can see the size of the string with strlen(str) for example.
Then you affect your copy pointer to an integer which has the value 0 (the character '\0'). It is the same as copy = NULL, which is what the printf() function shows you.
sizeof() returns the size of the actual type of the variable. So, when you define your type as char *, it returns the size of a pointer.
But if you made your variable an array, sizeof would return the size of the array itself, which would do what you want to do:
char *ptr = "moo to you";
char arr[] = "moo to you";
assert(sizeof(ptr) == 4); // assuming 32 bit
assert(sizeof(arr) == 11); // sizeof array includes terminating NUL
assert(strlen(arr) == 10); // strlen does not include terminating NUL
To tackle your second questions, by executing the statement copy++ you have changed the value of copy (that is, the address in memory that holds a char array) so that by the time you print it out, it is pointing at the end of the array rather than the beginning (the value returned by malloc()). You will need an extra variable to update the string and be able to access the beginning of the string:
Edit to repair malloc/sizeof issue - thanks CL.
char * str = "string";
/* char * copy = malloc(sizeof(str) + 1); Oops */
char * copy = malloc(strlen(str) + 1);
char * original_copy = copy;
printf("bytes allocated for copy: %d\n", sizeof(copy));
while(*str != '\0'){
*copy = *str;
str++;
copy++;
}
copy = '\0';
printf("%s\n", original_copy);
sizeof() returns you the size of the pointer and not the amount of allocated bytes. You don't need to count the allocated bytes, just check if the returned pointer is not NULL.
The line copy = '\0'; resets the pointer and makes it NULL.
You can use:
size_t malloc_usable_size (void *ptr);
instead of : sizeof
But it returns the real size of the allocated memory block! Not the size you passed to malloc!

how to copy stuff from getenv()? [duplicate]

Can someone explain to me why my call to malloc with a string size of 6 returns a sizeof of 4 bytes? In fact, any integer argument I give malloc I get a sizeof of 4. Next, I am trying to copy two strings. Why is my ouput of the copied string (NULL)?
Following is my code:
int main()
{
char * str = "string";
char * copy = malloc(sizeof(str) + 1);
printf("bytes allocated for copy: %d\n", sizeof(copy));
while(*str != '\0'){
*copy = *str;
str++;
copy++;
}
copy = '\0';
printf("%s\n", copy);
}
sizeof(str) returns the size of a pointer of type char*. What you should do is to malloc the size of the string it self:
char * copy = malloc(strlen(str) + 1);
Also, these lines:
while(*str != '\0'){
*copy = *str;
str++;
copy++;
}
copy = '\0';
Can be rewritten easily in C like this:
while(*copy++ = *str++);
First you should understand that sizeof(xxx) where xxx is any left value expression (a variable) is always equivalent to do sizeof(type of xxx). Hence what is really doing your sizeof(str) is returning the size of a char *, that is the size of any other pointer. On a 32 bits architecture you'll get 4, on a 64 bits architecture it'll be 8, etc.
So, as others also explained you have to know the length of the string you want to allocate, and then add 1 to store the terminal \0, C implicitly use to put at the end of strings.
But to do what you want (copy a string and allocate necessary space) it will be more simple and more efficient to use strdup, that does exactly that : a malloc and a strcopy.
You should also not forget to free space you allocated yourself (using malloc, calloc, strdup or any other allocation function). In C it won't go away when allocated variable go out of scope. It will stay used until the end of the program. That's what you call a memory leak.
#include <string.h> /* for strdup, strlen */
#include <stdio.h> /* for printf */
int main()
{
char * str = "string";
char * copy = strdup(str);
printf("bytes at least allocated for copy: %d\n", strlen(copy)+1);
printf("%s\n", copy);
free(copy);
}
One last point : I changed message to bytes at least allocated because you don't really know the size allocated when calling malloc. It quite often allocates a slighly more space that what you asked for. One reason is that in many memory managers free blocks are linked together using some hidden data structure and any allocated block should be able to contain at least such structure, another is that allocated blocks are always aligned in such a way to be compatible with any type alignment.
Hope it will help you to understand C a little better.
You're getting the size of the str pointer (4 bytes), not what it's pointing to?
sizeof(str) returns the space necessary to store the pointer to the string, not the string itself. You can see the size of the string with strlen(str) for example.
Then you affect your copy pointer to an integer which has the value 0 (the character '\0'). It is the same as copy = NULL, which is what the printf() function shows you.
sizeof() returns the size of the actual type of the variable. So, when you define your type as char *, it returns the size of a pointer.
But if you made your variable an array, sizeof would return the size of the array itself, which would do what you want to do:
char *ptr = "moo to you";
char arr[] = "moo to you";
assert(sizeof(ptr) == 4); // assuming 32 bit
assert(sizeof(arr) == 11); // sizeof array includes terminating NUL
assert(strlen(arr) == 10); // strlen does not include terminating NUL
To tackle your second questions, by executing the statement copy++ you have changed the value of copy (that is, the address in memory that holds a char array) so that by the time you print it out, it is pointing at the end of the array rather than the beginning (the value returned by malloc()). You will need an extra variable to update the string and be able to access the beginning of the string:
Edit to repair malloc/sizeof issue - thanks CL.
char * str = "string";
/* char * copy = malloc(sizeof(str) + 1); Oops */
char * copy = malloc(strlen(str) + 1);
char * original_copy = copy;
printf("bytes allocated for copy: %d\n", sizeof(copy));
while(*str != '\0'){
*copy = *str;
str++;
copy++;
}
copy = '\0';
printf("%s\n", original_copy);
sizeof() returns you the size of the pointer and not the amount of allocated bytes. You don't need to count the allocated bytes, just check if the returned pointer is not NULL.
The line copy = '\0'; resets the pointer and makes it NULL.
You can use:
size_t malloc_usable_size (void *ptr);
instead of : sizeof
But it returns the real size of the allocated memory block! Not the size you passed to malloc!

size of string returned by malloc is not correct

Why the size of the following allocated string (i.e. result) is not correct in the following code
#include <stdlib.h>
char *concat(const char *s1, const char *s2)
{
char *result;
result = malloc( strlen(s1) + strlen(s2) + 1 );
printf("%d", sizeof(result)); // <-- ????? ( it should be seven)
if ( result == NULL ){
printf("Error: malloc failed in concat\n");
exit(EXIT_FAILURE);
}
strcpy(result, s1);
strcpy(result, s2);
return result;
}
int main()
{
char *p;
p = concat("abc", "def");
return 0;
}
Edit:
I'm trying to allocate an enough size for the new string but for somehow the size is not correct.
In this case sizeof is evaluated at compile time, and it pays no attention to the size of the allocated block.
The expression returns the size of pointer, which is fixed for the hardware platform.
Unfortunately, there is no way of finding the allocated size returned by malloc. If you want to know the size of an allocated block, you need to store the size in a separate variable.
sizeof(result) will give the size of a pointer probably 4 or 8, so you cant use it for that.
Immediately after calling malloc you should check it's return value, on error it returns NULL, if the value is not NULL then it points to uninitialized content.
To get the length of a string you need strlen function, but if the contents are not initialised it would be undefined behavior.
You need to use strlen after you fill the buffer with data, the data is terminated with a '\0' byte which marks the end of the string, it wouldn't be there if you haven't initialized the data.

Reading line from file causes crash

I'm trying to read a line from a file character by character and place the characters in a string; here' my code:
char *str = "";
size_t len = 1; /* I also count the terminating character */
char temp;
while ((temp = getc(file)) != EOF)
{
str = realloc(str, ++len * sizeof(char));
str[len-2] = temp;
str[len-1] = '\0';
}
The program crashes on the realloc line. If I move that line outside of the loop or comment it out, it doesn't crash. If I'm just reading the characters and then sending them to stdout, it all works fine (ie. the file is opened correctly). Where's the problem?
You can't realloc a pointer that wasn't generated with malloc in the first place.
You also have an off-by-one error that will give you some trouble.
Change your code to:
char *str = NULL; // realloc can be called with NULL
size_t len = 1; /* I also count the terminating character */
char temp;
while ((temp = getc(file)) != EOF)
{
str = (char *)realloc(str, ++len * sizeof(char));
str[len-2] = temp;
str[len-1] = '\0';
}
Your issue is because you were calling realloc with a pointer to memory that was not allocated with either malloc or realloc which is not allowed.
From the realloc manpage:
realloc() changes the size of the memory block pointed to by ptr to size bytes.
The contents will be unchanged to the minimum of the old and new
sizes; newly allocated memory will be uninitialized. If ptr is NULL,
then the call is equivalent to malloc(size), for all values of size;
if size is equal to zero, and ptr is not NULL, then the call is
equivalent to free(ptr). Unless ptr is NULL, it must have been
returned by an earlier call to malloc(), calloc() or realloc(). If
the area pointed to was moved, a free(ptr) is done.
On a side note, you should really not grow the buffer one character at a time, but keep two counter, one for the buffer capacity, and one for the number of character used and only increase the buffer when it is full. Otherwise, your algorithm will have really poor performance.
You can't realloc a string literal. Also, reallocing every new char isn't a very efficient way of doing this. Look into getline, a gnu extension.

Resources