Memory corruption in the last byte - c

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.

Related

in c why the dereference of the s point to string value not working?

why when i use the program it return s = null
the get_string function can have update to make the program work
it is : string s = malloc(sizeof(string));
but in the end of the function and after return s; i cant free(s);
or before return s; i will lose the data i stored
i tried to search more about dereference pointers but i got nothing.
#include <stdio.h>
typedef char* string;
string get_string(string q)
{
string s = NULL;
printf("%s",q);
scanf("%s",s);
return s;
}
int main(void)
{
string a = get_string("name : ");
printf("name is %s\n",a);
}
Here are two correct uses of scanf to read a string:
char s1[10];
scanf("%9s", s1);
char *s2 = malloc(100);
scanf("%99s", s2);
Notice that in both cases — s1 and s2 — I had to explicitly say how much memory I wanted for my string. Then, when I called scanf, I included that information — 1 less than the overall string size — in the %s format, so that I could tell scanf not to read a bigger string than my string variable could hold.
Notice, by contrast, that in your get_string function, you did not allocate any memory to hold your string at all. Your variable s was a null pointer, explicitly pointing to no memory at all.
This is something that's very easy to overlook at first: Most of the time, C does not allocate memory for strings for you. Most of the time, this is your responsibility.
Now, an additional concern is that even when you do allocate memory for a string, you have to think about how long that memory will stick around, and whether anyone has to explicitly deallocate it. And there are some additional mistakes that are easy to make. In particular, suppose you took my first example (s1) to heart, and tried to fix your get_string function like this:
char *get_string(char *q)
{
char s[100]; /* WRONG */
printf("%s",q);
scanf("%99s",s);
return s;
}
Here you have given scanf a proper array to read in to, but it's local to the get_string function, meaning that it will disappear after get_string returns, and it will be useless to the caller.
Another possibility is
#include <stdlib.h>
char *get_string(char *q)
{
char s = malloc(100); /* better */
if(s == NULL) {
fprintf(stderr, "out of memory!\n");
exit(1);
}
printf("%s",q);
scanf("%99s",s);
return s;
}
This will work just fine. Note that I have checked to see whether malloc succeeded. (If it fails, it returns a NULL pointer.) But now we have the issue that some memory has been allocated which might never be freed. That is, get_string returns a pointer to dynamically-allocated memory, and it's the caller's responsibility to free that memory when it's no longer needed. The caller doesn't have to, but if there end up being 1,000,000 calls to get_string, and if none of the allocated blocks ever gets freed, that's a lot of memory wasted.
First as other people have noted in the comments the Typedef in this case isn't very helpful as it hides the fact its a pointer. Also char* is vary commonly used and not a type complicated enough for a typedef IMO.
For your other issues the problem appears to be that you are thinking of the value as a C++ string instead of a char pointer. In C there aren't string objects but instead people use char* which can pointer blocks of chars and we determine the end of the string by putting a null character at the end of list of characters.
So the reason you can't print the NULL string is because it is undefined behavior to pass a NULL pointer to printf. When you change it to s = malloc(sizeof(string)); the pointer is no longer null but instead pointing to the start of a block of memory that is sizeof(string) bytes long. You should be doing malloc(sizeof(char)*strlen(q)); instead so you have a block of memory holding a string with the length of string q instead of just one character. More generally it would be malloc(sizeof(char)*NUM_CHARS);.
When it come to the free call. You can't call free(s) after return s; because no statements after return s; will occur because the function has returned and no longer executing. As for calling before, calling free(s) deallocates that block of memory that s is pointing too from the malloc(sizeof(string)) is pointing to. Here you have to remember that the function isn't returning the memory or the string but instead it returns the pointer to the string. So if you delete the memory the pointer is pointing to then you lose it once you return.

fread removes a different previously assigned character string

I'm reading in a binary file using fread, but in the process of this operation, another character string is changed into (null). Below is the part of the code that seems to cause the problem. The entire code is much longer, and my suspicion is that I'm running into problems with the available stack memory, but I don't know how to verify that.
char *foo;
foo = argv[1];
double *array;
array= malloc(npts*sizeof(double)); //npts - number of points
FILE *fo = fopen(ofile, "r");
printf("String: %s\n",foo);
fread(&array,8,npts,fo);
printf("String: %s\n",foo);
The first occurence of the print statement returns the previously assigned value 'bar', but the second returns '(null)'.
I expected both of the print statements to return 'bar'.
The &array in fread(&array,8,npts,fo); is wrong; that is the address of the pointer. You should pass the pointer: fread(array,8,npts,fo);.

Malloc array of characters dynamic vs static C

So I'm basically trying to take an input of scanf of letters (no spacing between them), place each letter into an array and spit out the corresponding letter to the array by using dynamically allocated arrays (malloc).
Crashes
#include <stdio.h>
#include <stdlib.h>
int main () {
char *userInput = malloc(sizeof(char)*3); /* dynamic */
scanf("%s", &userInput);
printf("user inputed %c", userInput[1]);
free(userInput);
return 0;
}
Runs
#include <stdio.h>
#include <stdlib.h>
int main () {
char userInput [3]; /* array */
scanf("%s", &userInput);
printf("user inputed %c", userInput[1]);
return 0;
}
Input:
asd
Output:
s
My understanding of dynamically allocated arrays was that char userInput [3]; is equivalent to char *userInput = malloc(sizeof(char)*3); but apparently from this case that isn't true? Anyone care to explain/help?
Welcome to Stack Overflow! Coincidentally, the main problem with your code is that it is vulnerable to a stack overflow. scanf has no way of knowing how big userInput is, because you didn't tell it, and will happily continue filling memory long past the end of your very short array.
If you want to capture exactly three characters (with no nul terminator), use scanf("%3c", userInput) instead. Note that without the NUL, you must not expect to treat userInput as a string; printing it via printf for example will result in a random amount of gibberish owing to the fact that C does not know where the string ended.
Now, to answer your actual question on "what's the difference between malloc and the static array": the difference is of scope. If you only ever use userInput before its creating function returns, there is no practical difference, but you're in trouble the minute you try to do something like this:
int function1 {
char my_string[3];
scanf("%3c", my_string);
return my_string; /* WRONG! DANGER! */
}
The return in the above example will happily return the pointer to my_string to the calling function. However, as soon as function1 returns, the stack is rolled back and the memory my_string occupied is essentially gone (and likely already re-used). The results are unpredictable but almost universally very bad for your program.
However, had you used malloc() instead, you could safely return the my_string pointer and the memory would persist until someone later called free(my_string) (where my_string is the pointer to the original my_string; it need not be named the same!).
This highlights another difference: with a stack variable such as char my_string[3];, you do not need to worry about (and indeed cannot) free() the memory, where as if the memory is malloc()'d instead, you must free() it if you wish to reclaim the memory.
There are some nuances to the above, such as file-scoped variables and static function variables, which I leave as topics for further reading.
As pointed in Giorgi's answer, the main problem is the incorrect usage of the address-of operator &.
However, the reason why it worked on one case and why it didn't work on another is very interesting.
char array[3]: When you declare that array, memory space will be allocated for it and array will be a label to that location(memory address). When you pass array to scanf (or use it anywhere else without subscripting []), you're passing an address to that function. Because of that, when you use the & operator on the label array, it returns the same address to you BUT with different type (T(*)[3]), which your compiler probably complained about. But, as the memory address is valid, it worked as expected.
char *array = malloc(): When you declare that variable, memory is also reserve for it, but this time in a different place and the space reserved is sizeof T(*), so it can hold a memory address. This variable also has an address in memory, which you can also get using &array. Then you malloc some memory and malloc returns to you an address of a memory block which you can now use. You can get that memory address by simply doing array. So, when you call scanf with the &array you're passing the variable address instead of the block address. That's why it crashes (I'm guessing you were not entering only two characters).
Check this code:
#include <stdio.h>
#include <stdio.h>
int main(void)
{
char *array[3];
char *ptr = malloc(3 * sizeof(char));
printf ("array : %p\n", array);
printf ("&array: %p\n\n", &array);
printf ("ptr : %p\n", ptr);
printf ("&ptr : %p\n", &ptr);
scanf("%s", &ptr);
printf ("ptr : %p\n", ptr);
return 0;
}
Which outputs:
$ ./draft
array : 0x7ffe2ad05ca0
&array: 0x7ffe2ad05ca0
ptr : 0x19a4010
&ptr : 0x7ffe2ad05c98
ABCD
ptr : 0x44434241
scanf got the address of the pointer, so when it saves the value it reads from stdin, it overwrites the address we had from malloc! The memory block we had is now gone, memory is leaking... Now, this is bad because we're overwriting stuff on our stack, memory is leaking, and it will crash.
Observe the last output: the value of ptr (which previously was the address of an allocated block) is now 0x44434241 (DCBA, ASCII Table)! How nice is that?

Issues printing whilst using getline()

I'm just having a bit of difficulty with a print. Basically, I have code and I'm assigning values to bestmatch[], which is defined as being of type line_t (see struct at bottom).
As you can see, I am storing values for bestmatch[].score (double), bestmatch[].index (int) and bestmatch[].buf (string). When I print them, show in second code block below, bestmatch[i].index and bestmatch[i].score print correctly; however, bestmatch[i].buf does not print at all.
Just to confuse matters more (for myself at least), if I print bestmatch[i].buf at the end of scorecmp (first code block), it prints fine. I've got my call to scorecmp down the very bottom for reference.
Why is it that it is printing index and score fine, but not buf? Or even more, how can I fix this behaviour?
Thank you for your help! Please let me know if you need any additional information
The print, appearing in main, is as follows (for reference, TOP_SCORING_MAX is the number of elements in bestmatch[]):
int i;
for (i = 0; i<TOP_SCORING_MAX; i++) {
if (bestmatch[i].score != -1) {
printf("line\t%d, score = %6.3f and string is %s \n",
bestmatch[i].index,bestmatch[i].score, bestmatch[i].buf);
}
}
And in case you would like the struct:
typedef struct line_t {
char* buf;
int lineLength;
int wordCount;
int index;
double score;
} line_t;
This is my call to scorecmp:
scorecmp(linePtr, bestmatch);
You need to copy the content of the strings, not just the pointers, because they seem to be destroyed, freed, or mutilated before you print them:
bestmatch[j].buf = strdup(linePtr->buf);
Don't forget to free the copied string at the end.
The getline function is the preferred method for reading lines of text from a stream.
The other standard functions, such as gets, fgets and scanf, are a little too unreliable.
The getline function reads an entire line from a stream, up to and including the next newline character.
This function takes three parameters:
A pointer to a block of memory allocated with malloc or calloc. This parameter is of type char**, and it will contain the line read by getline when the function returns.
A pointer to a variable of type size_t. This parameter specifies the size in bytes of the block of memory pointed to by the first parameter.
The stream from which to read the line.
The first parameter - a pointer to the block of memory allocated with malloc or calloc - is merely a suggestion. Function getline will automatically enlarge the block of memory as needed via realloc, so there is never a shortage of space - one reason why this function is so safe. Not only that, but it will also tell you the new size of the block, by updating the value returned in the second parameter.
That being said, every time you call function getline, you first need to:
Set maxSz to a reasonable size.
Set line.buf = malloc(maxSz).
Set the value of maxSz not too large, in order to reduce the amount of redundant memory used.
Set the value of maxSz not too small, in order to reduce the number of times getline calls realloc.

Pointer and Function ambiguity in C

Please look at the following code:
char* test ( )
{
char word[20];
printf ("Type a word: ");
scanf ("%s", word);
return word;
}
void main()
{
printf("%s",test());
}
When the function returns, the variable word is destroyed and it prints some garbage value. But when I replace
char word[20];
by char *word;
it prints the correct value. According to me, the pointer variable should have been destroyed similar to the character array and the output should be some garbage value. Can anyone please explain the ambiguity?
Undefined behavior is just that - undefined. Sometimes it will appear to work, but that is just coincidence. In this case, it's possible that the uninitialized pointer just happens to point to valid writeable memory, and that memory is not used for anything else, so it successfully wrote and read the value. This is obviously not something you should count on.
You have undefined behavior either way, but purely from a "what's going on here" viewpoint, there's still some difference between the two.
When you use an array, the data it holds is allocated on the stack. When the function returns, that memory will no longer be part of the stack, and almost certainly will be overwritten in the process of calling printf.
When you use the pointer, your data is going to be written to whatever random location that pointer happens to have pointed at. Though writing there is undefined behavior, simple statistics says that if you have (for example) a 32-bit address space of ~4 billion locations, the chances of hitting one that will be overwritten in the new few instructions is fairly low.
You obviously shouldn't do either one, but the result you got isn't particularly surprising either.
Because the char array is defined and declared in the function, it is a local variable and no longer exists after the function returns. If you use a char pointer and ALLOCATE MEMORY FOR IT then it will remain, and all you need is the pointer (aka a number).
int main(int argc, char* argv[]) {
printf("%s", test());
return 0;
}
char* test(void) {
char* str = (char*)malloc(20 * sizeof(char));
scanf("%19s", str);
return str;
}
Notice how I used %19s instead of %s. Your current function can easily lead to a buffer overflow if a user enters 20 or more characters.
During program execution first it will create activation records for the function main in stack segment of the process memory. In that main activation records it will allocate memory for the local variable of that function(main) and some more memory for internal purpose. In your program main doesn't has any local variable, so it will not allocate any memory for local variables in main activation records.
Then while executing the statement for calling the function test, it will create one more activation records for the calling function(test) and it will allocate 20 bytes for the local variable word.
Once the control exits the function test, activation record created for that function will be poped out of that stack. Then it will continue to execute the remaining statment (printf) of the called function main. Here printf is trying to print the characters in the test function's local variable which is already poped out of the stack. So this behaviour is undefined, sometimes it may print the proper string or else it will print some junk strings.
So in this situation only dynamic memory comes into picture. With the help of dynamic memory we can control the lifetime(or scope) of a variable. So use dynamic memory like below.
char *word = NULL:
word = (char *) malloc(sizeof(char) * 20);
Note : Take care of NULL check for the malloc return value and also dont forget to free the allocated memory after printf in main function.

Resources