This question is aimed at improving my understanding of
what I can and cannot do with pointers when allocating and freeing:
The bellow code is not meant to run, but just set up a situation for the questions bellow.
char *var1 = calloc(8,sizeof(char));
char **var2 = calloc(3,sizeof(char*));
var1 = "01234567";
var1[2] = '\0';
var1[5] = '\0';
//var1 = [0][1][\0][3][4][\0][6][7]
var2[0] = var1[0];
var2[1] = var1[3];
var2[2] = var1[6];
free(var1);
free(var2);
given the following snippet
1: is it ok to write to a location after the \0 if you know the size you allocated.
2: Can I do what I did with var2 , if it points to a block that another pointer is pointing at?
3: are the calls to free ok? or will free die due to the \0 located throughout var1.
I printed out all the variables after free, and only the ones up to the first null got freed (changed to null or other weird and normal looking characters). Is that ok?
4: Any other stuff you wish to point out that is completely wrong and should be avoided.
Thank you very much.
Ok, let's just just recap what you have done here:
char *var1 = calloc(8,sizeof(char));
char **var2 = calloc(3,sizeof(char*));
So var1 is (a pointer to) a block of 8 chars, all set to zero \0.
And var2 is (a pointer to) a block of 3 pointers, all set to NULL.
So now it's the program's memory, it can do whatever it wants with it.
To answer your questions specifically ~
It's quite normal to write characters around inside your char block. It's a common programming pattern to parse string buffers by writing a \0 after a section of text to use everyday C string operations on it, but then point to the next character after the added \0 and continue parsing.
var2 is simply a bunch of char-pointers, it can point to whatever char is necessary, it doesn't necessarily have to be at the beginning of the string.
The calls to free() are somewhat OK (except for the bug - see below). It's normal for the content of free()d blocks to be overwritten when they are returned to the stack, so they often seem to have "rubbish" characters in them if printed out afterwards.
There is some issues with the assignment of var1 ~
var1 = "01234567";
Here you are saying "var1 now points to this constant string". Your compiler may have generated a warning about about this. Firstly the code assigns a const char* to a char* (hard-coded strings are const, but C compilers will only warn about this [EDIT: this is true for C++, not C, see comment from n.m.]). And secondly, the code lost all references to the block of memory that var1 used to point to. You can now never free() this memory - it has leaked. However, at the end of the program, the free() is trying to operate on a pointer-to a block of memory (the "01234567") which was not allocated on the heap. This is BAD. Since you're exiting immediately, there's no ill-effects, but if this was in the middle of execution, the next allocation (or next 1000th!) could crash weirdly. These sorts of problems are hard to debug.
Probably what you should have done here (I'm guessing your intention though) is used a string copy:
strncpy(var1, "01234567", 8);
With that operation instead of the assignment, everything is OK. This is because the digits are stored in the memory allocated on line1.
Question 4 - what's wrong
You 'calloc' some memory and store a pointer to it in var1. Then later you execute var1 = "01234567" which stores a pointer to a literal string in var1, thus losing the calloc'd memory. I imagine you thought you were copying a string. Use strcpy or similar.
Then you write zero values into what var1 points to. Since that's a literal string, it may fail if the literal is in read-only memory. The result is undefined.
free(var1) is not going to go well with a pointer to a literal. Your code may fail or you may get heap corruption.
Pointers don't work this way.
If someone wrote
int a = 6*9;
a = 42;
you would wonder why they ever bothered to initialise a to 6*9 in the first place — and you would be right. There's no reason to. The value returned by * is simply forgotten without being used. It could be never calculated in the first place and no one would know the difference. This is exactly equivalent to
int a = 42;
Now when pointers are involved, there's some kind of evil neural pathway in our brain that tries to tell us that a sequence of statements that is exactly like the one shown above is somehow working differently. Don't trust your brain. It isn't.
char *var1 = calloc(8,sizeof(char));
var1 = "01234567";
You would wonder why they ever bothered to initialise var1 to calloc(8,sizeof(char)); in the first place — and you would be right. There's no reason to. The value returned by calloc is simply forgotten without being used. It could be never calculated in the first place and no one would know the difference. This is exactly equivalent to
char* var1 = "01234567";
... which is a problem, because you cannot modify string literals.
What you probably want is
char *var1 = calloc(8, 1); // note sizeof(char)==1, always
strncpy (var1, "01234567", 8); // note not strcpy — you would need 9 bytes for it
or some variation of that.
var1 = "01234567"; is not correct because you assign a value of pointer to const char to a pointer to mutable char and causes a memory leak because the value of pointer to a calloc allocated buffer of 8 char stored in variable var1 is lost. It seems like you actually intended to initialize allocated array with the value of the string literal instead (though that would require allocation of an array of 9 items). Assignment var1[2] = '\0'; causes undefined behavior because the location var1 points to is not mutable. var2[0] = var1[0]; is wrong as well because you assign a value of char to pointer to char. Finally free(var1); will try to deallocate a pointer to buffer baking string literal, not something you allocated.
Related
I have some very basic questions regarding pointers and memory allocation.
In below code where does pointer c actually point to? In other words where does the string "xyz" get stored in memory (stack/heap etc.)?
What will happen to memory location allocated for a as I am not using it anymore?
Code seems to work well if I un-comment the commented section. What's happening with the memory in that scenario?
#include <stdio.h>
main()
{
char *c;
//c = (char *)malloc(2);
c = "a";
c = "xyz" ;
printf("%s",c);
return 0;
}
Output:
xyz
Edit:
After reading few of the answer and first comment another question came up in my mind:
In below case, where do the strings get stored? Can I alter them later on?
char *c[] = {"a","xyz"};
The specific details are implementation dependent, but in most common implementations, literal strings like "a" and "xyz" are stored in the text section of the program, like the machine code that implements the program. Assigning a = "xyz"; sets a to point to that location in memory.
The memory for "a" is unaffected. However, an optimizing compiler may notice that c was never used between that assignment and being reassigned, so it could simply ignore the first assignment, and never allocate any space for "a" at all.
The memory you allocated with malloc() stays allocated until the program ends. Allocating memory without freeing it is called a memory leak, and you should try to avoid it.
1.In below code where does pointer 'c' is actually pointing to?In other words where does the string "xyz" get stored in memory(stack/heap etc.)?
will place xyz the read-only parts of the memory and making c a pointer to that, a variable of type pointer-to-char, called c , which is initialized with the location of the first character in that unnamed, read-only array.you created automatic storage (often called the stack). Here you just point to memory in text section.
2.What will happen to memory location allocated for"a"' as i am not using it anymore?
As per your code you not allocated any memory just you assign string literals to that.If you allocate then need to free it.
3.Code seems to work well if I un-comment the commented section.Whats happening with memory in that scenario?
If you un comment the allocation statement to allocate memory then also it point to you literal string but you need to free that memory.
Now for case
char *c[] = {"a","xyz"};
when you declare and initialize words, it'll be allocated on the stack as any other automatic array and its items will be assigned to pointers to the beginning of each string constant.Also to alter this string may illegal.
"xyz" and "a" are string literals which is mostly available in string table.
"xyz" is printed because it is recently assigned to that pointer.
To a place in the heap/stack in the READ-ONLY part of the memory which the string is in. When assigning a string literal directly into a pointer, the program searches for that string in the memory, if it exists through the short search he's doing, it'll point to it, if it doesn't - it will create it. Either way it's read only so it'll be the same as a const char* so you can't change it (of course you can somehow manipulate it, maybe by another pointer or so).
Nothing, it'll stay unaffected.
What's happening is that malloc returns a pointer and you just ignore it, you go to another address containing a and it will not have the same influence as strcpy(c, "a"); as you ignore the allocated memory and its pointer - you do not free it. Generally, nothing's happen if you don't free the memory (I mean, at the end of the program it is freed automatically by the OS) but it WILL take memory within the program so if i'd allocate, let's say 1000000 bytes (assuming it succeeded), allocating more heap memory would be a problem :P
about the other question... You can't alter them through that pointer, try and it will throw an interrupt in the middle of the program and it'll probably stop responding.
char * a = (char *) malloc(10);
strcpy(a,"string1");
char * x = "string2";
strcat(a,x);
printf("\n%s",a);
Here, I allocated only 10B to a, but still after concatenating a and x (combined size is 16B), C prints the answer without any problem.
But if I do this:
char * a = "string1";
char * x = "string2";
strcat(a,x);
printf("\n%s",a);
Then I get a segfault. Why is this? Why does the first one work despite lower memory allocation? Does strcat reallocate memory for me? If yes, why does the second one not work? Is it because a & x declared that way are unmodifiable string literals?
In your first example, a is allocated in the heap. So when you're concatenating the other string, something in the heap will be overwritten, but there is no write-protection.
In your second example, a points to a region of the memory that contains constants, and is readonly. Hence the seg fault.
The first one doesn't always work, it already caused an overflow. The second one, a is a pointer to the constant string which is stored in the data section, in a read-only page.
In the 2nd case what you have is a pointer to unmodifiable string literals,
In 1st case, you are printing out a heap memory location and in that case its undefined, you cannot guarantee that it will work every time.
(may be write it in a very large loop, yo may see this undefined behavior)
Your code is writing beyond the buffer that it's permitted, which causes undefined behavior. This can work and it can fail, and worse: it can look like it worked but cause seemingly unrelated failures later. The language allows you to do things like this because you're supposed to know what you're doing, but it's not recommended practice.
In your first case, of having used malloc to allocate buffers, you're actually being helped but not in a manner you should ever rely on. The malloc function allocates at least as much space as you've requested, but in practice it typically rounds up to a multiple of 16... so your malloc(10); probably got a 16 byte buffer. This is implementation specific and it's never a good idea to rely on something like that.
In your second case, it's likely that the memory pointed to by your a (and x) variable(s) is non-writable, which is why you've encountered a segfault.
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...
I have been trying to look for a reason why the following code is failing, and I couldn't find one.
So please, excuse my ignorance and let me know what's happening here.
#include<stdio.h>
int main(void){
char* p="Hi, this is not going to work";
scanf("%s",p);
return 0;
}
As far as I understood, I created a pointer p to a contiguous area in the memory of the size 29 + 1(for the \0).
Why can't I use scanf to change the contents of that?
P.S Please correct me If I said something wrong about char*.
char* p="Hi, this is not going to work";
this does not allocate memory for you to write
this creates a String Literal which results inUndefined Behaviour every time you try to change its contents.
to use p as a buffer for your scanf do something like
char * p = malloc(sizeof(char) * 128); // 128 is an Example
OR
you could as well do:
char p[]="Hi, this is not going to work";
Which I guess is what you really wanted to do.
Keep in mind that this can still end up being UB because scanf() does not check whether the place you are using is indeed valid writable memory.
remember :
char * p is a String Literal and should not be modified
char p[] = "..." allocates enough memory to hold the String inside the "..." and may be changed (its contents I mean).
Edit :
A nice trick to avoid UB is
char * p = malloc(sizeof(char) * 128);
scanf("%126s",s);
p points to a constant literal, which may in fact reside in a read-only memory area (implementation dependent). At any rate, trying to overwrite that is undefined behaviour. I.e. it might result in nothing, or an immediate crash, or a hidden memory corruption which causes mysterious problems much later. Don't ever do that.
It is crashing because memory has not been allocated for p. Allocate memory for p and it should be ok. What you have is a constant memory area pointing to by p. When you attempt to write something in this data segment, the runtime environment will raise a trap which will lead to a crash.
Hope this answers your question
scanf() parses data entered from stdin (normally, the keyboard). I think you want sscanf().
However, the purpose of scanf() is to part a string with predefined escape sequences, which your test string doesn't have. So that makes it a little unclear exactly what you are trying to do.
Note that sscanf() takes an additional argument as the first argument, which specifies the string being parsed.
I have this function which is called about 1000 times from main(). When i initialize a pointer in this function using malloc(), seg fault occurs, possibly because i did not free() it before leaving the function. Now, I tried free()ing the pointer before returning to main, but its of no use, eventually a seg fault occurs.
The above scenario being one thing, how do i initialize double pointers (**ptr) and pointer to array of pointers (*ptr[])?
Is there a way to copy a string ( which is a char array) into an array of char pointers.
char arr[]; (Lets say there are fifty such arrays)
char *ptr_arr[50]; Now i want point each such char arr[] in *ptr_arr[]
How do i initialize char *ptr_arr[] here?
What are the effects of uninitialized pointers in C?
Does strcpy() append the '\0' on its own or do we have to do it manually? How safe is strcpy() compared to strncpy()? Like wise with strcat() and strncat().
Thanks.
Segfault can be caused by many things. Do you check the pointer after the malloc (if it's NULL)? Step through the lines of the code to see exactly where does it happen (and ask a seperate question with more details and code)
You don't seem to understand the relation of pointers and arrays in C. First, a pointer to array of pointers is defined like type*** or type**[]. In practice, only twice-indirected pointers are useful. Still, you can have something like this, just dereference the pointer enough times and do the actual memory allocation.
This is messy. Should be a separate question.
They most likely crash your program, BUT this is undefined, so you can't be sure. They might have the address of an already used memory "slot", so there might be a bug you don't even notice.
From your question, my advice would be to google "pointers in C" and read some tutorials to get an understanding of what pointers are and how to use them - there's a lot that would need to be repeated in an SO answer to get you up to speed.
The top two hits are here and here.
It's hard to answer your first question without seeing some code -- Segmentation Faults are tricky to track down and seeing the code would be more straightforward.
Double pointers are not more special than single pointers as the concepts behind them are the same. For example...
char * c = malloc(4);
char **c = &c;
I'm not quite sure what c) is asking, but to answer your last question, uninitialized pointers have undefined action in C, ie. you shouldn't rely on any specific result happening.
EDIT: You seem to have added a question since I replied...
strcpy(..) will indeed copy the null terminator of the source string to the destination string.
for part 'a', maybe this helps:
void myfunction(void) {
int * p = (int *) malloc (sizeof(int));
free(p);
}
int main () {
int i;
for (i = 0; i < 1000; i++)
myfunction();
return 0;
}
Here's a nice introduction to pointers from Stanford.
A pointer is a special type of variable which holds the address or location of another variable. Pointers point to these locations by keeping a record of the spot at which they were stored. Pointers to variables are found by recording the address at which a variable is stored. It is always possible to find the address of a piece of storage in C using the special & operator. For instance: if location were a float type variable, it would be easy to find a pointer to it called location_ptr
float location;
float *location_ptr,*address;
location_ptr = &(location);
or
address = &(location);
The declarations of pointers look a little strange at first. The star * symbol which stands in front of the variable name is C's way of declaring that variable to be a pointer. The four lines above make two identical pointers to a floating point variable called location, one of them is called location_ptr and the other is called address. The point is that a pointer is just a place to keep a record of the address of a variable, so they are really the same thing.
A pointer is a bundle of information that has two parts. One part is the address of the beginning of the segment of memory that holds whatever is pointed to. The other part is the type of value that the pointer points to the beginning of. This tells the computer how much of the memory after the beginning to read and how to interpret it. Thus, if the pointer is of a type int, the segment of memory returned will be four bytes long (32 bits) and be interpreted as an integer. In the case of a function, the type is the type of value that the function will return, although the address is the address of the beginning of the function executable.
Also get more tutorial on C/C++ Programming on http://www.jnucode.blogspot.com
You've added an additional question about strcpy/strncpy.
strcpy is actually safer.
It copies a nul terminated string, and it adds the nul terminator to the copy. i.e. you get an exact duplicate of the original string.
strncpy on the other hand has two distinct behaviours:
if the source string is fewer than 'n' characters long, it acts just as strcpy, nul terminating the copy
if the source string is greater than or equal to 'n' characters long, then it simply stops copying when it gets to 'n', and leaves the string unterminated. It is therefore necessary to always nul-terminate the resulting string to be sure it's still valid:
char dest[123];
strncpy(dest, source, 123);
dest[122] = '\0';