Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 5 years ago.
Improve this question
I am writing a function in C. What I found is that when I debug in gdb, I found a pointer "result" has the same address with another pointer before "result" was declared. Part of my code:
char* stringSum(char* x, char* y){
puts(x);
puts(y);
printf("\n");
int lengthx=strlen(x);
int lengthy=strlen(y);
int lengths=MIN(lengthx,lengthy);
int lengthl=MAX(lengthx,lengthy);
char* s=((lengthx<=lengthy)?x:y);
char* l=((lengthx>lengthy)?x:y);
int returnSize=MAX(lengthx, lengthy)+2;//-----I could print result now
printf("before, short is : ");puts(s);
char* result=malloc(sizeof(char)*returnSize);//-----but result is allocated now
printf("after allocate memory for result, short is: ");puts(s);//---s is changed!
result[returnSize-1]='\0';
......
}
This function get the sum of two numbers (in string) so that I could calculate the sum of two large numbers. In gdb: I got this weird problem:
My problems are in red and yellow rectangles
(When debug in gdb) Before char* result=malloc(sizeof(char)*returnSize); I print s and result (so now it haven't been declared yet) and got
(gdb) print s
$5 = 0x61f950 "6597242170048699800240000000000"
(gdb) print result
$6 = 0x61f950 "6597242170048699800240000000000"
I couldn't understand that since how could an undeclared pointer points to an existing address? (This function is called by another function with a very large number of x and y (in string). If I changed them to relatively small values I will always get the right answer. What's more, if I create a new .c file and only have this function and main function, I will not have that problem anymore even with a large value.)
My second problem is that I have printed s twice and I found the second time I print (after declare the pointer result) s is changed! (Similar to the first problem, if I choose smaller values for x and y or create a new .c file, I will not have the same problem.)
I guess I have some problem with malloc but after search online I haven't find any useful resources will could help me solve the problem. Do I have the problem about memory management?
You have at least two serious problems with your code.
The first problem is that you never free what you malloc, creating sizeable memory leaks at each recursive call.
The second problem is that you are trying to assign strings, which doesn't have the effect you hope for.
Here is an example of what you do (comments mine):
// allocate some memory and assign its address to abcd
char* abcd=malloc(sizeof(char)*returnSize);
// throw it away by assigning a different value to abcd
abcd=karatsuba(stringSum(a,b),stringSum(c,d));
// then assign yet another different value to abcd
abcd=stringSubstract(abcd,ac);
// and another one
abcd=stringSubstract(abcd,bd);//ab+cd
// Code below overflows, because memory abcd is pointing to is
// not the original block allocated for it (you threw it away).
// It is a block allocated and returned by stringSubstract.
// Its length is not necessarily sufficient to accommodate all
// the data you are trying to stuff in it.
int labcd=strlen(abcd);
for(i=0;i<=(ns/2-1);i++){
abcd[labcd+i]='0';
}
abcd[lac+i]='\0';
You can verify that this is the case by running your program under valgrind. You will get error messages that indicate a buffer overflow just before the mysterious shortening of s. It all goes downhill from there.
In order to fix the problem, you may want to use strcpy instead of pointer assignment. Another way to fix it would be ditching the abcd = malloc(...) lines in the beginning of the function, and using realloc to make sure they have the allocations have enough size.
In addition you definitely want to fix the memory leaks. You need to call free for each variable you malloc after you're done with it. If you are returning a malloced variable, the caller needs to free it after using it.
Related
I want to write a C code to see the difference between static and dynamic allocation.
That's my idea but it doesn't work.
It simply initializes an array of size 10, but assigns 100 elements instead of 10. I'll then initialize another array large enough hoping to replace the 90 elements that're not part of array1[10], then I print out the 100 elements of array1.
int i;
int array1[10];
int array2[10000];
for(i=0;i<100;i++)
array1[i] = i;
for(i=0;i<10000;i++)
array2[i] = i+1;
for(i=0;i<100;i++)
{
printf("%d \n",array1[i]);
}
What I hope to get is garbage outside then first 10 elements when using static allocation, afterwards, I'll use malloc and realloc to ensure that the 100 elements would be there correctly. But unfortunately, it seems that the memory is large enough so that the rest of the 100 elements wouldn't be replaced!
I tried to run the code on linux and use "ulimit" to limit the memory size, but it didn't work either.
Any ideas please?
Cdoesn't actually do any boundary checking with regards to arrays. It depends on the OS to ensure that you are accessing valid memory.
Accessing outside the array bounds is undefined behavior, from the c99 draft standard section Annex J.2 J.2 Undefined behavior includes the follow point:
An array subscript is out of range, even if an object is apparently accessible with the
given subscript (as in the lvalue expression a[1][7] given the declaration int
a[4][5]) (6.5.6).
In this example you are declaring a stack based array. Accessing out of bound will get memory from already allocated stack space. Currently undefined behavior is not in your favor as there is no Seg fault. Its programmer's responsibility to handle boundary conditions while writing code in C/C++.
You do get garbage after the first 10 elements of array1. All of the data after element 9 should not be considered allocated by the stack and can be written over at any time. When the program prints the 100 elements of array1, you might see the remnants of either for loop because the two arrays are allocated next to each other and normally haven't been written over. If this were implemented in a larger program, other arrays might take up the space after these two example arrays.
When you access array1[10] and higher index values, the program will just keep writing into adjacent memory locations even though they don't "belong" to your array. At some point you might try to access a memory location that's forbidden, but as long as you're mucking with memory that the OS has given to your program, this will run. The results will be unpredictable though. It could happen that this will corrupt data that belongs to another variable in your program, for example. It could also happen that the value that you wrote there will still be there when you go back to read it if no other variable has been "properly assigned" that memory location. (This seems to be what's happening in the specific case that you posted.)
All of that being said, I'm not clear at all how this relates to potential differences between static and dynamic memory allocation since you've only done static allocation in the program and you've deliberately introduced a bug.
Changing the memory size won't resolve your problem, because when you create your two arrays, the second one should be right after the first one in memory.
Your code should do what you think it will, and on my computer, it does.
Here's my output :
0
1
2
3
4
5
6
7
8
9
10
11
1
2
3
4
5
...
What OS are you running your code on ? (I'm on linux 64bit).
Anyway, as everybody told you, DON'T EVER DO THIS IN A REAL PROGRAM. Writing outside an array is an undefined behaviour and could lead your program to crash.
Writing out of bounds of an array will prove nothing and is not well-defined. Generally, there's nothing clever or interesting involved in invoking undefined behavior. The only thing you'll achieve by that is random crashes.
If you wish to know where a variable is allocated, you have to look at addresses. Here's one example:
#include <stdio.h>
#include <stdlib.h>
int main (void)
{
int stack;
static int data = 1;
static int bss = 0;
int* heap = malloc(sizeof(*heap));
printf("stack: %p\n", (void*)&stack);
printf(".data: %p\n", (void*)&data);
printf(".bss: %p\n", (void*)&bss);
printf(".heap: %p\n", (void*)heap);
}
This should print 4 distinctively different addresses (.data and .bss probably close to each other though). To know exactly where a certain memory area starts, you either need to check some linker script or use a system-specific API. And once you know the memory area's offset and size, you can determine if a variable is stored within one of the different memory segments.
Pretty new to C, but I thought I had the hang of allocating and managing memory until I ran into this issue recently.
I am working on a "make" utility. (It's not homework, just my friend's old assignment that I thought I could glean valuable practice from.) As I'm sure most of you know, makefiles have various targets, and these targets have depdendencies that must be attended to before the targets's commands can be executed.
In order to store data for a given target's dependencies found while parsing the makefile I made the following:
typedef struct{
char* target;
char** dependency_list;
}dependency_tracker;
In order to keep track of multiple dependency_trackers, I declared (and subsequently allocated for) the following variable. (NOTICE the "+4" after "total_number_of_targets". THE PROGRAM DOESN'T WORK WITHOUT IT, AND MY QUESTION IS WHY THAT IS.)
dependency_tracker** d_tracker_ptr = (dependency_tracker**) malloc((total_number_of_targets+4)*sizeof(dependency_tracker*));
I then sent the pointer for this to the parsing method with the following line:
parse_file(filename,&d_tracker_ptr);
Within the parse_file function, I believe these are the most important calls I make (left out string parsing calls). Note that target_counter is the number of targets parsed so far. I think everything else should be somewhat manageable to figure out:
dependency_tracker** tracker_ptr = *tracker_ptr_address; // tracker_ptr_address is the pointer I passed to the function above
// declare and allocate for the new struct we are creating
dependency_tracker* new_tracker_ptr = (dependency_tracker*) malloc(sizeof(dependency_tracker));
char* new_tracker_ptr_target = (char*) malloc((size_of_target)*sizeof(char)); // size_of_target is the string length
new_tracker_ptr->target = new_tracker_ptr_target;
*(tracker_ptr+target_counter*sizeof(dependency_tracker*)) = new_tracker_ptr;
As I mentioned earlier, I have to allocate space for four more (dependency_tracker*)'s than I would have thought I needed to in order for this program to complete without a segfault.
I came to the conclusion that this was because I was overwriting the space I had allocated for the pointer I pass to parse_file.
My question is: why does this happen? Even if space for a NULL pointer is needed, that shouldn't require the space of 4 additional pointers. And the program produces a segfault if I allocate anything less than 25 additional bytes in the original call to malloc
Let me know if anything needs clarification. I know this is a bit of a novel.
This is broken:
*(tracker_ptr+target_counter*sizeof(dependency_tracker*)) = new_tracker_ptr;
The pointer size is accounted for by C. You want:
tracker_ptr[target_counter] = new_tracker_ptr;
Also as I mentioned in comments, you did not allow for a null terminator in the strings.
Another comment: C does not require a cast on malloc, and using one invites trouble. Also it's safer to just dereference the pointer you're assigning to inform sizeof. So just say:
dependency_tracker *new_tracker_ptr = malloc(sizeof *new_tracker_ptr);
char* new_tracker_ptr_target = malloc(size_of_target * sizeof *new_tracker_ptr_target);
dependency_tracker *new_tracker_ptr = malloc(*new_tracker_ptr);
new_tracker_ptr->target = new_tracker_ptr_target;
Additionally, you may want to reconsider the vacuous words in your variable names. I'm actually a big fan of longish, explanatory identifiers, but "tracker" and "target" are so vague that they add little clarity. Similarly, embedding type information in variable names a la _ptr was a fad about 30 years ago. It's over now. If you have a function where the declaration and a variable name can't be grok'ed on the same screen, the function is too big.
*(tracker_ptr+target_counter*sizeof(dependency_tracker*)) = ...
This is the problem. Pointer arithmetic doesn't work like that. You do not have to multiply by sizeof(anyhing) when using properly typed (i.e. not char*) pointer arithmetic. What's better, you don't have to use pointer arithmetic at all.
tracker_ptr[target_counter] = ...
is all that's needed.
I'm trying to make a program that basically picks a specific piece of source code and adds some other specific code into it. The program is just to big to put it all inside my question, but basically I have this "actors" struct:
typedef struct actors_s {
int num;
char *src_path;
char *project_path;
int *papify;
char *actor_path[];
} actors_s;
As you can see these are almost all pointers and the last one is an array of strings. This needs to be done this way because the number of "actor elements" depends on the input every time.
The problem:In an specific test case, I have a case with 'num' members in the actor_path array. Then I first call malloc only once this way:
*actors->actor_path = malloc(actors->num);
My logic tells me I shouldn't be using the '*' operator here but without it I get an error, this is possibly where the problem is. So, a function is called that allocates a new memory space for every new member (never going further of 'num' members):
int size = strlen(name)+strlen(actors->project_path)+strlen("/src/")+strlen(".c")+4;
actors->actor_path[i] = malloc(size);
(The malloc calls are properly tested if successful in the actual program)
This is called inside a function that is called for every "actor_path" element. In this test example I have three actors.
Mysteriously enough, on the third call of this malloc, the src_path element of the struct, which was properly allocated and set to a string once in the beginning of the program (and never touched again) is freed (I think so, at least it is changed into random numbers and symbols if I watch it in debug mode).
Anyone has any idea how and why is this possible? How do I fix this?
Thanks in advance.
EDIT:
Here are some screenshots from the debug watch window: http://imgur.com/a/aB1uv
First call to malloc: all OK.
Second call to malloc: all OK.
Third call to malloc: src_path gets erased!!
[] in latest array element is called flexible array member. It means structure have an array that starts just after structure itself, and its size is unspecified. You have to allocate memory for this manually. E.g.
actors_s *actor = malloc(sizeof(*actor) + sizeof(char*) * num);
Then just assign at most num elements into actor_path (each element is pointer to char).
about *actors->actor_path = malloc(actors->num);
actors->actor_path is an array of pointers, so *actors->actor_path is the first pointer in actors->actor_path, i.e. actors->actor_path[0].
When doing this, you actually allocate actors->num bytes memory for actors->actor_path[0].
Now, accessing actors->actor_path[0] is OK, while accessing actors->actor_path[1], actors->actor_path[2], actors->actor_path[3],... may cause problems, say, rewrite src_path...
about the solution
#keltar is right. In this way, the resource for actors->actor_path[0], actors->actor_path[1], actors->actor_path[2], ..., actors->actor_path[num - 1] is correctly allocated.
This is my code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(){
char *dd,aaa[500];
strcpy(aaa,"test 1");
dd=aaa;
printf("1. %s\n",dd);
strcpy(aaa,"test 2");
printf("2. %s\n",dd);
system("pause");
return 0;
}
When i have changed aaa variable by test 2 string, dd also changes, why?
It could be great if you said what you are trying to do in order for others to put your code into perspective.
Now you seem to have not understood well how pointers work. Since your code isn't really easy to read, the answer will be general.
Pointers 'hold' addresses to memory. If you have pointer ptr1 pointing towards memory block A and pointer ptr2 pointing towards ptr1, if you change ptr1, naturally ptr2 will experience the same changes. In your first block of code, you seem not to understand why someVar changes after otherVar changes. To make more explicit what #dmp has pointed out, you have told you program ( the operating system is managing memory for your program ) that someVar will point towards the value held in otherVar[0]. Now when otherVar[0] changes, someVar will change because that is how pointers are supposed to work, it is called to dereference a pointer - when you request the value of what the pointer points to - and you'll notice that things changed pr ptr2. So, please reread about pointers again.
In your second block of code, I don't know what you trying to accomplish but whatever it is, it will SEGFAULT. That is so because again, you haven't understood the relationship between pointers, arrays and how dynamic memory allocation works. For example, in the splittext function you have this line:
wchar_t *arr[2],*loc = wcsstr(stri, del), buf[DEFAULT_BUFLEN];
Right there: you telling the operating system to check the value at the 3rd cell of *arr while you haven't allocated memory for it. Also, when allocating memory, remember:
If you want to allocate memory for char to get a string your pointer will have to be a pointer towards char like this:
char* my_string = malloc( 256*sizeof(char))
Now you want to get memory allocated to pointers towards say variables of type FILE*.
If you write FILE** my_files = malloc( NUMBER_OF_FILES*sizeof(FILE)) it will get you into trouble. Rather write :
FILE** my_files = malloc( NUMBER_OF_FILES*sizeof(FILE*))
This is with regards to how you allocated memory for say arr.
Also don't cast the return value of malloc. It will hide many errors the compiler could have caught!
To sum up, first try to learn about pointers before moving on to a bit advanced uses of pointers, arrays and memory allocation; second you can't put incorrect code ( you will know it is incorrect either it doesn't compile or just crash ) and tell others : "hey look at that variable, that is where my problem is." Try to do more research into the question, try learning what tools can assist - a debugger in this case - and that will be improve the quality of your question. Third and last, if English is not your first language, you can mention it and others will be willing to assist in reformulating your question.
Hope you will do better next time!
UPDATE
After edit by OP, the question now is clearer and the OP's problem is about pointers.
dd's value changes because:
aaa is a pointer like this: char aaa[500] is equivalent to char* aaa = malloc(500*sizeof(char)). Now when you dd=aaa, you told the compiler that dd will point to the same memory address as does aaa. So every time you modify aaa dd gets modified because they point to the same thing in memory.
If that wasn't clear, try to reread the definition of a pointer.
What you ask is not clear, however, pointers in C are passed by value (there is a copy of the pointer pointing to the same location). If you dereference a pointer and change the value pointed to, the caller will see the change.
A quick pointer lesson should clear it up:
What happens on this line?
char *dd = aaa;
You've created a pointer to a character allocation called dd and pointed it to the memory address that aaa is stored at.
aaa's address is on the stack and static (you created it implicitly with your aaa[500]).
Now, when you put data into aaa, aaa's location in memory does not change, simply the data stored at that position in memory. When you try to print out the 'contents' of aaa, you're getting the characters stored at that point in memory. When you copy new data into aaa, the position in memory still remains the same, and thus dd is still pointing to the same memory space as aaa does.
My apologies if that's no clearer than anyone else's...
Here is my code
#include<stdio.h>
int * fun(int a1,int b)
{
int a[2];
a[0]=a1;
a[1]=b;
//int c=5;
printf("%x\n",&a[0]);
return a;
}
int main()
{
int *r=fun(3,5);
printf("%d\n",r[0]);
printf("%d\n",r[0]);
}
I am running codeblocks on Windows 7
Every time I run the loop I get the outputs as
22fee8
3
2293700
Here is the part I do not understand :
r expects a pointer to a part of memory which is interpreted as a sequence of boxes (each box of 4 byte width - >Integers ) on invoking fun function
What should happen is printf of function will print the address of a or address of a[0]:
Seconded
NOW THE QUESTION IS :
each time I run the program I get the same address?
And the array a should be destroyed at the end of Function fun only pointer must remain after function call
Then why on earth does the line r[0] must print 3?
r is pointing to something that doesn't exist anymore. You are returning a pointer to something on the stack. That stack will rewind when fun() ends. It can point to anything after that but nothing has overwritten it because another function is never called.
Nothing forces r[0] to be 3 - it's just a result of going for the simplest acceptable behaviour.
Basically, you're right that a must be destroyed at the end of fun. All this means is that the returned pointer (r in your case) is completely unreliable. That is, even though r[0] == 3 for you on your particular machine with your particular compiler, there's no guarantee that this will always hold on every machine.
To understand why it is so consistent for you, think about this: what does is mean for a to be destroyed? Only that you can't use it in any reliable way. The simplest way of satisfying this simple requirement is for the stack pointer to move back to the point where fun was called. So when you use r[0], the values of a are still present, but they are junk data - you can't count on them existing.
This is what happens:
int a[2]; is allocated on the stack (or similar). Suppose it gets allocated at the stack at address 0x12345678.
Various data gets pushed on the stack at this address, as the array is filled. Everything works as expected.
The address 0x12345678 pointing at the stack gets returned. (Ironically, the address itself likely gets returned on the stack.)
The memory allocated on the stack for a ceases to be valid. For now the two int values still sit at the given address in RAM, containing the values assigned to them. But the stack pointer isn't reserving those cells, nor is anything else in the program keeping track of that data. Computers don't delete data by erasing the value etc, they delete cells by forgetting that anything of use is stored at that memory location.
When the function ends, those memory cells are free to be used for the rest of the program. For example, a value returned by the function might end up there instead.
The function returned a pointer to a segment on the stack where there used to be valid data. The pointer is still 0x12345678 but at that address, anything might be stored by now. Furthermore, the contents at that address may change as different items are pushed/popped from the stack.
Printing the contents of that address will therefore give random results. Or it could print the same garbage value each time the program is executed. In fact it isn't guaranteed to print anything at all: printing the contents of an invalid memory cell is undefined behavior in C. The program could even crash when you attempt it.
r is undefined after the stack of the function int * fun(int a1,int b) is released, right after it ends, so it can be 3 or 42 or whatever value. The fact that it still contains your expected value is because it haven't been used for anything else, as a chunk of your memory is reserved for your program and your program does not use the stack further. Then after the first 3 is printed you get another value, that means that stack was used for something else, you could blame printf() since it's the only thing runing and it does a LOT of things to get that numbers into the console.
Why does it always print the same results? Because you always do the same process, there's no magic in it. But there's no guarantee that it'll be 3 since that 'memory space' is not yours and you are only 'peeking' into it.
Also, check the optimization level of your compiler fun() and main(), being as simple as they are, could be inline'd or replaced if the binary is to be optimized reducing the 'randomness' expected in your results. Although I wouldn't expect it to change much either.
You can find pretty good answers here:
can-a-local-variables-memory-be-accessed-outside-its-scope
returning-the-address-of-local-or-temporary-variable
return-reference-to-local-variable
Though the examples are for C++, underlying idea is same.