C:string getting corrupted between malloc and strcpy - c

I am very confused why this is happening though I've used such statements well before. I am copying one string into other simply and my original string is getting corrupted, even before strtok gets called. This is the relevant code snippet, after this I am using strtok. But before that I'm seeing reference got corrupted.
int j, sizeref;
char *str1, *token;
printf("%s :", reference);
sizeref = strlen(reference);
printf("%d\n", sizeref);
track = malloc(sizeref);
printf("%s :", reference);
strcpy(track, reference);
printf("%d\n", strlen(track));
This is the output below. The first line prints whole reference and correct size as 234. After that I see only 106 characters got copied and original string reference is also truncated to 106 characters. track is declared as char *
+918956549122,9527529747,09847778399,08596774833,9867859469,+919999866778,6985888696,5968939898,6959869856,9898495895,6986596865,09847765399,88596774833,9967859469,+917899866778,6985889696,9527567747,09848778399,08596756733,9867999469 :234
+918956549122,9527529747,09847778399,08596774833,9867859469,+919999866778,6985888696,5968939898,69598698 :106
MORE INFO: reference is getting build up incrementally in chunks of 50 bytes. Once completely built , then only being used as mentioned above. char * reference is global , and getting built up inside main. Above mentioned code is inside a separate function
realloc(reference,strlen(reference) + CHUNK);

According to manual on strlen():
DESCRIPTION
The strlen() function calculates the length of the string s,
excluding the terminating null byte ('\0').
So, as mentioned above, you should allocate buffer of size strlen() + 1 for correct null termination.

C strings are null terminated. Change the code to track=malloc(sizeref + 1);, otherwise strcpy will attempt to write the null termination outside valid memory.

You are probably trying to get the size of the array by using sizeof in a function where the array decays to a pointer and sizeof returns only the size of pointer.

Related

\n is not substituted using strtok

I am trying to use the C's strtok function in order to process a char* and print it in a display, and looks like that for some reason I don't know the character '\n' is not substituted by '\0' as I believe strtok does. The code is as follows:
-Declaration of char* and pass to the function where it will be processed:
char *string_to_write = "Some text\nSome other text\nNewtext";
malloc(sizeof string_to_write);
screen_write(string_to_write,ALIGN_LEFT_TOP,I2C0);
-Processing of char* in function:
void screen_write(char *string_to_write,short alignment,short I2C)
{
char *stw;
stw = string_to_write;
char* text_to_send;
text_to_send=strtok(stw,"\n");
while(text_to_send != NULL)
{
write_text(text_to_send,I2C);
text_to_send=strtok(NULL, "\n");
}
}
When applying the code, the result can be seen in imgur (Sorry, I am having problems with format adding the image here in the post), where it can be seen that the \n is not substituted as it is the strange character appearing in the image, and the debugger still showed the character as well. Any hints of where can the problem be?
Thanks for your help,
Javier
strtok expects to be able to mutate the string you pass it: instead of allocating new memory for each token, it puts \0 characters into the string at token boundaries, then returns a series of pointers into that string.
But in this case, your string is immutable: it's a constant stored in your program, and can't be changed. So strtok is doing its best: it's returning indices into the string for each token's starting point, but it can't insert the \0s to mark the ends. Your device can't handle \ns in the way you'd expect, so it displays them with that error character instead. (Which is presumably why you're using this code in the first place.)
The key is to pass in only mutable strings. To define a mutable string with a literal value, you need char my_string[] = "..."; rather than char* my_string = "...". In the latter case, it just gives you a pointer to some constant memory; in the former case, it actually makes an array for you to use. Alternately, you can use strlen to find out how long the string is, malloc some memory for it, then strcpy it over.
P.S. I'm concerned by your malloc: you're not saving the memory it gives you anywhere, and you're not doing anything with it. Be sure you know what you're doing before working with dynamic memory allocation! C is not friendly about that, and it's easy to start leaking without realizing it.
1.
malloc(sizeof string_to_write); - it allocates the sizeof(char *) bytes not as many bytes as your string needs. You also do not assign the allocated block to anything
2.
char *string_to_write = "Some text\nSome other text\nNewtext";
char *ptr;
ptr = malloc(strlen(string_to_write) + 1);
strcpy(ptr, string_to_write);
screen_write(ptr,ALIGN_LEFT_TOP,I2C0);

The necessity to memset with '\0', in a toy example

I encountered the following example of using memset in tutorialspoint:
#include <stdio.h>
#include <string.h>
int main(){
char src[40];
char dest[100];
memset(dest, '\0', sizeof(dest));
strcpy(src, "This is tutorialspoint.com");
strcpy(dest, src);
printf("Final copied string : %s\n", dest);
return(0);
}
I don't get why the memset line is used, as the compile and result are the same when that line is commented. I would like to ask is that line necessary? or is it a good practice to do so when doing strcpy()? or it is just one random line.
Thanks!
It's not needed in this case, in the sense that it has no effect on the output. It might be needed in some similar cases.
char dest[100];
This defines dest as a local array of 100 chars. Its initial value is garbage. It could have been written as:
char dest[100] = "";
or
char dest[100] = { 0 };
but none of those are necessary because dest is assigned a value before it's used.
strcpy(src, "This is tutorialspoint.com");
strcpy(dest, src);
This copies the string contained in src into the array dest. It copies the 26 characters of "This is tutorialspoint.com" plus 1 additional character, the terminating '\0; that marks the end of the string. The previous contents of the dest array are ignored. (If we were using strcat(), it would matter, because strcat() has to find a '\0' in the destination before it can start copying.)
Without the memset() call, the remaining 73 bytes of dest would be garbage -- but that wouldn't matter, because we never look at anything past the '\0' at dest[26].
If, for some reason, we decided to add something like:
printf("dest[99] = '%c'\n", dest[99]);
to the program, then the memset() would matter. But since the purpose of dest is to hold a string (which is by definition terminated by a '\0' null character), that wouldn't be a sensible thing to do. Perfectly legal, but not sensible.
the posted code could skip the initialization via memset().
A time it really becomes useful is when debugging and you use the debugger to display the contents of the variable.
Another time to use memset() is when allocating something like an array of pointers, which might not all be set to point to something specific, like more allocated memory.
Then when passing those pointers to 'free()the unused pointers are set to NULL, so will not cause a crash when passed tofree()`

Memory corruption in the last byte

I have a function that returns a pointer to a structure as the following :
//header file
typedef struct {
unsigned char *buffer;
uint8_t len;
} T_ABC_PACKET
in the main file, I create a pointer to a function and tries to print this
T_ABC_PACKET *pct = NULL;
pct = function_that_return_the_packet;
printf("value of packet is %s \n", pct->buffer);
the result is always consistent in the printing function. I expect the buffer to have an 8 byte, and the last byte is always a corrupted memory.
value is 10000357`�2U
but if I print the buffer inside the function :
T_ABC_PACKET* function_that_return_the_packet {
T_ABC_PACKET *pct = NULL;
char string_temp[80];
//some more initialization...
pct->buffer = (unsigned char *)string_temp;
pct->len = 5;
printf("value of packet is %s \n", pct->buffer);
return pct;
}
the value printed in the function is 10000357f. Only the last character is corrupted.
This always provide a consistent value, no many times I run the program, only the last character is corrupted in the caller of the function.
I understand one possible case is memory leak, but I tried to check carefully and I can not find any leak. How do I get the pct->buffer to have everything correctly?
It looks like you are returning a pointer to a local variable which is undefined behavior, string_temp is local to function_that_return_the_packet and will not exist after you exit that function.
As Daniel suggested using strdup is probably the simplest way to fix the problem:
pct->buffer = strdup(string_temp);
Just make sure you check that it did not fail. You could of course also use malloc and then strcpy.
Once you fix the undefined behavior of returning a pointer to local (see Shafik Yaghmour answer) you still have undefined behavior: it appears that the buffer is not null-ternminated, so %s format specifier reads past it, and stops only when it finds an unrelated \0.
If you know that the buffer's length cannot exceed eight, you can copy its content up to pct->len into a char buffer, theninsert a terminator at the end:
char tmpBuf[9]; // max length is 8, plus one for null ternminator
memcpy(tmpBuf, pct->buffer, pct->len);
tmpBuf[pct->len] = '\0';
printf("value of packet is %s \n", tmpBuf);
This is the source of the problem:
pct->buffer = (unsigned char *)string_temp;
'string_temp' is allocated on the stack. When function returns, it is destroyed somewhere later, or not, as in your case, except last byte.
You should:
Use strdup() instead of assignment in that line.
When you are done with whole structure, use free() to release that string before releasing whole structure.

How can I pass a dynamic array (malloced) to a function?

I need to pass a char * to a function, but this function really needs const?
But I'm reading it from file and it's dynamic for me:
fseek(fcode, 0, SEEK_END);
i=ftell(fcode);
square_scm = (char*) malloc(i);
//free(square_scm);
fseek(fcode, 0, SEEK_SET);
fread(square_scm, 1, i, fcode);
scheme_load_string(sc, square_scm);
So square_scm here is:
"(display
(string-append "Answer: "
(number->string (square 6.480740698407859)) "\n"))юоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюоюо"
without free :
"(display
(string-append "Answer: "
(number->string (square 6.480740698407859)) "\n"))ННээээ««««««««««««««««ю"
How can I make it like char[size], like:
"(display
(string-append "Answer: "
(number->string (square 6.480740698407859)) "\n"))"
?
Your free() is a disaster; you only free() the data when you've finished with it.
You should probably be error checking the return codes, at least of malloc() and fread().
The data read from the file will not be null terminated. You need to over-allocate by one byte and add the terminal NUL ('\0') after reading the data into your allocated buffer. (Note that the file might have shrunk since you opened it; pay attention to the value returned from fread(). If the file grew, you won't see the extra data, but no other damage will occur.)
You ask about const. Presumably the function square_cm() has a signature such as:
void square_cm(SomeType *sc, const char *data_string);
and you are worried that you have a char * and not a const char * in your calling code?
You do not need to be concerned; the compiler will 'add const' for you. The const is actually a promise to you, the user of the function, that the function itself will not modify your data. It can take a fixed string (eg a string constant) or a dynamically allocated string, and it doesn't matter. Where you run into problems is when you have a const char * or a string literal that you need to pass to a function that takes a char *. Here the function does not self-evidently promise to leave the string alone, which can cause problems. For example, you can't pass a string literal to strtok() because the function tries to modify the string, but the string is probably in read-only memory, which triggers problems (core dumps on Unix; undefined behaviour everywhere).
So, const in a function signature is a promise to the consumer (user) of the function not to change something. You can pass const or non-const data to that function because it won't be modified either way.
You are using a freed pointer, which causes undefined behaviour. You should delete or move the free() call.
You aren't null terminating the string after you read it from the file. You should null terminate that string. Something like:
square_scm[i] = 0;
Make sure the you have allocated enough space to allow for the null terminator - that means adding a +1 to your malloc() call.
Alternately, you can add a maximum field width to your printf() call:
printf("%*s", i, string);
Though you haven't shown the code where the printing happens, so that may or may not be practical.
You should probably also do some error checking.
Don't free the malloced memory until you are done with it. And to answer your question, always leave space for the terminating null byte in the strings and do set the last byte to null byte.
fseek(fcode, 0, SEEK_END);
i=ftell(fcode);
//allocate for null byte too
square_scm = malloc(i + 1);
//reset the memory before using it
memset(square_scm, 0, i + 1);
fseek(fcode, 0, SEEK_SET);
fread(square_scm, 1, i, fcode);
square_scm[i] = 0; //not really required as we have already memset it
scheme_load_string(sc, square_scm);
//now you should free it, assuming it is not used anymore
free(square_scm);

Wrong strlen output

I have the following piece of code in C:
char a[55] = "hello";
size_t length = strlen(a);
char b[length];
strncpy(b,a,length);
size_t length2 = strlen(b);
printf("%d\n", length); // output = 5
printf("%d\n", length2); // output = 8
Why is this the case?
it has to be 'b [length +1]'
strlen does not include the null character in the end of c strings.
You never initialized b to anything. Therefore it's contents are undefined. The call to strlen(b) could read beyond the size of b and cause undefined behavior (such as a crash).
b is not initialized: it contains whatever is in your RAM when the program is run.
For the first string a, the length is 5 as it should be "hello" has 5 characters.
For the second string, b you declare it as a string of 5 characters, but you don't initialise it, so it counts the characters until it finds a byte containing the 0 terminator.
UPDATE: the following line was added after I wrote the original answer.
strncpy(b,a,length);
after this addition, the problem is that you declared b of size length, while it should be length + 1 to provision space for the string terminator.
Others have already pointed out that you need to allocate strlen(a)+1 characters for b to be able to hold the whole string.
They've given you a set of parameters to use for strncpy that will (attempt to) cover up the fact that it's not really suitable for the job at hand (or almost any other, truth be told). What you really want is to just use strcpy instead. Also note, however, that as you've allocated it, b is also a local (auto storage class) variable. It's rarely useful to copy a string into a local variable.
Most of the time, if you're copying a string, you need to copy it to dynamically allocated storage -- otherwise, you might as well use the original and skip doing a copy at all. Copying a string into dynamically allocated storage is sufficiently common that many libraries already include a function (typically named strdup) for the purpose. If you're library doesn't have that, it's fairly easy to write one of your own:
char *dupstr(char const *input) {
char *ret = malloc(strlen(input)+1);
if (ret)
strcpy(ret, input);
return ret;
}
[Edit: I've named this dupstr because strdup (along with anything else starting with str is reserved for the implementation.]
Actually char array is not terminated by '\0' so strlen has no way to know where it sh'd stop calculating lenght of string as as
its syntax is int strlen(char *s)-> it returns no. of chars in string till '\0'(NULL char)
so to avoid this this we have to append NULL char (b[length]='\0')
otherwise strlen count char in string passed till NULL counter is encountered

Resources