I am playing with array and pointer and got this segmentation fault. Can any one explain why I have been getting this segmentation fault in this code when I move my pointer "p" below "ptr" pointer in the code and when I comment out one of printf statement alternatively it disappears:
typedef struct str{
char* ptr;
}str_t;
copy(str_t t){
char a[12];
char *p; // <------ no error when move below ptr pointer
char *ptr;
printf("t= %s p = %d ptr = %d\n", t, p, ptr);
strcpy(a, t.ptr);
printf("a = %s %u\n", a, &a);
strcpy(ptr, t.ptr);
printf("ptr = %s %u\n", ptr, &ptr); //<--- comment it error disappears
p= t.ptr;
printf("p = %s %u",p, &p); //<--- comment it error disappears
}
int main ()
{
str_t t;
char app[] = "hello";
char ap[] ="world";
t.ptr = ap;
copy(t);
printf("%s\n", app);
return 0;
}
you can compile the code here to see the result :
http://codepad.org/Q7zS8NaC
Thank you , for visiting this question .
strcpy doesn't allocate space at the pointer, p, to store the string. You need to declare it as an array or allocate space with malloc or calloc.
Try this:
int len = strlen (t.ptr); // find length of string
char * ptr = calloc (len + 1, 1); // allocate space for ptr
if (!ptr) return; // error check calloc
strcpy (ptr, t.ptr); // copy the string
char * p = calloc (len + 1, 1); // do the same thing for p
if (!p) return;
strcpy (p, t.ptr);
That will fix your segmentation fault.
You have a couple of more errors though, which are mainly format issues.
%u prints an unsigned integer. It looks like you're trying to print a pointer, so use %p instead.
printf("t= %s p = %d ptr = %d\n", t, p, ptr); is totally wrong.
You need to reference the member of t, which is t.ptr
p is a pointer, not an integer. Use %p instead of %d
ptr is also a pointer. Use either %p or %s
Read the documentation of printf if you're ever unsure about formatting. In fact, read the documentation of any function, if you are unsure how to use it - you'll save yourself a lot of headaches.
Your code has several undefined behaviors:
The first printf prints a pointer using %d specifier
The second call of strcpy call attempts to write to memory pointed to by an uninitialized pointer
The second and third calls of printf passes a pointer to an array to a format specifier %u
Removing one of the pointers makes the code not crash, but since undefined behavior is there, the code does not work correctly, and may crash at any time.
Here is one way of fixing it:
char a[12];
char *p;
char *ptr;
printf("t= %s p = %x ptr = %x\n", t.ptr, (void*)p, (void*)ptr);
strcpy(a, t.ptr);
printf("a = %s %x\n", a, (void*)(&a[0]));
ptr = malloc(strlen(t.ptr)+1);
// In production, check ptr for NULL
strcpy(ptr, t.ptr);
printf("ptr = %s %x\n", ptr, (void*)&ptr);
p= t.ptr;
printf("p = %s %x", p, (void*)&p);
// Release the memory when you are done
free(ptr);
Related
The method signature for getenv
char *getenv(const char *name)
The return value is a pointer to char .
Now if we look at the below example :
#include <stdio.h>
#include <stdlib.h>
int main()
{
char *p;
p = getenv("PATH");
if(p != NULL)
printf("Current path is %s", p);
return 0;
}
The only confusion here is the "p" printed with format specifier "%s" as String but what about the Pointer Dereference
If I put "*p" instead, I end up with segmentation fault
while if I want to get the pointer address I can do this
printf("%p", p);
confusion about getting the value by deferencing the point "p" in our case.
Please explain
Looks like you're confused about some fundamental basics in C.
In case of
char *p;
p is a pointer to a series of char, which is in fact a \0 terminated
string. This string can be printed with printf("%s", p);
Since p is a pointer you can print the memory address it points to printf("%p", p);, which is exactly the same as if p was defined as void *p;
*p dereferences the first char in the string pointed to by p, which is essentially the same as p[0]. This string can be printed with printf("%c", *p); or printf("%c", p[0]);
So I have this code in which allocation is happening in one function and deallocation is being done in the calling function. Getting Segmentation fault or Abort message while trying to free the memory either by ptr or *ptr. Kindly have a look:
#include <stdio.h>
int main()
{
char *ptr;
fun(&ptr);
printf("ptr = %p\n",ptr);
printf("&ptr = %p\n",&ptr);
printf("String ptr = %s\n",ptr);
free (ptr);
return 0;
}
void fun(char **str)
{
*str = malloc(10);
*str = "HELLO";
printf("str = %p\n",str);
printf("&str = %p\n",&str);
printf("String str = %s\n",*str);
}
Following is the output:
str = 0x7ffe63247858
&str = 0x7ffe63247838
String str = HELLO
ptr = 0x400764
&ptr = 0x7ffe63247858
String ptr = HELLO
*** Error in `/home/a.out': munmap_chunk(): invalid pointer: 0x0000000000400764 ***
Aborted
Question :
Why can't we free ptr ? And if we can, what is the best way to do it ?
you're overwriting the pointer value in the line after, making *str point to a literal.
So you have a memory leak and undefined behaviour by trying to free a literal.
You probably mean
strcpy(*str,"hello");
Note that those 2 lines could be changed into a working single line like this:
*str = strdup("HELLO");
which has the advantage of allocating the exact number of bytes for the string instead of guessing.
When you do *str = "HELLO"; it does not have the effect you expect. Instead of assigning value to the allocated memory, you are re-assigning the pointer to point to the string literal and thus later you try to deallocate it (thus the error). Instead of this you should use strcpy like strcpy(*str, "HELLO").
To answer the question of how to do this without explicit string copying, instead of
char *p = "hello";
do
char p[] = "hello";
The first points p to a non-modifiable portion of memory. The second allocates an array large enough to hold the literal and copies the literal into it.
you are changing memory address pointed str pointer after malloc in fun. you should do strcpy instead of direct assignment :
#include <stdio.h>
int main()
{
char *ptr;
fun(&ptr);
printf("ptr = %p\n",ptr);
printf("&ptr = %p\n",&ptr);
printf("String ptr = %s\n",ptr);
free (ptr);
return 0;
}
void fun(char **str)
{
*str = malloc(10);
strcpy(*str,"HELLO");//*str = "HELLO";
printf("str = %p\n",str);
printf("&str = %p\n",&str);
printf("String str = %s\n",*str);
}
I wrote this C code:
#include<stdio.h>
#include<string.h>
int main()
{
char *i, *p, *p1="Hello";
strcpy(p,p1); //The first strcpy works.
printf("%s\n", p); //show copy successful
printf("Please hit a key to continue....\n");
getchar();
strcpy(i,p); //The second strcpy causes stop working problem. Why?
printf("%s\n", i);
return 0;
}
Can anyone tell me why the second strcpy doesn't work?
I would say you were lucky the first strcpy worked in the first place!
You basically declared a POINTER to a char, nothing else.
What you need in order for strcpy to work correctly is make sure you have an array of char large enough to fit your copy in. In other words, allocate some memory first for your pointer, or use an array...
you need to allocate memory for the chars. you could e.g. do it like this:
char* p1 = "Hello";
char* i = (char*)malloc(sizeof(char) * 6);
char* p = (char*)malloc(sizeof(char) * 6);
please don't miss a free afterwards (before return):
free(p);
free(i);
Moreover an additional include is needed to use malloc and free:
#include<stdlib.h>
Your complete sample should be looking like this:
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
int main()
{
char* p1 = "Hello";
char* i = (char*)malloc(sizeof(char) * 6);
char* p = (char*)malloc(sizeof(char) * 6);
// 1st copy
strcpy(p,p1);
printf("1st copy: %s\n", p);
// 2nd copy
strcpy(i,p);
printf("2nd copy: %s\n", i);
getchar();
// free prior allocated memory
free(p);
free(i);
return 0;
}
The problem is that strcpy won't allocate memory for your string hence it will most likely crash if you haven't done so. I'd say its by chance the first instance works.
You're lucky the program only gives you a segmentation fault. You can either allocate memory using malloc or calloc or you use the function strdup to allocate memory for you.
char *i, *p, *p1="Hello";
p = strdup(p1);
printf("%s\n", p); //show copy successful
printf("Please hit a key to continue....\n");
getchar();
i = strdup(p);
printf("%s\n", i);
free(p);
free(i);
Don't forget to free the memory afterwards!
I'm having some trouble with memcpy throwing a segmentation fault, and I can't seem to locate the source of the error.
typedef struct {
int record_code;
char* record_name;
char buffer[6004];
} record;
record* rec;
char* ptr = rec->buffer;
//--DEBUG
printf("ADDR OF PTR: %p\n", ptr);
printf("SIZE OF BUFFER: %d\n", sizeof(ptr->buffer));
//--End DEBUG
create_record(ptr);
I want to add an int value into my buffer, but I'm getting a SEGFAULT on this line
memcpy(ptr, &key, sizeof(key));
in this function
int counter = 0;
int create_record(char* ptr) {
int key = counter;
//--DEBUG
printf("ADDR OF PTR: %p\n", ptr);
printf("SIZE OF KEY: %d\n", sizeof(key));
//--End DEBUG
memcpy(ptr, &key, sizeof(key));
ptr += sizeof(key);
int integer = rand_int();
memcpy(ptr, &integer, sizeof(integer));
ptr += sizeof(integer);
char* word = rand_string();
memcpy(ptr, word, strlen(word));
ptr += strlen(word);
counter++;
}
The only reasons I could think of memcpy throwing a segfault is if either pointers are garbage or the size of the thing I'm trying to throw into the memory location is greater than the memory I have allocated. But I'm merely trying to put an integer (size = 4 bytes) into a buffer allocated to be 6004 bytes, so it doesn't appear to be a sizing issue... and the address of the pointer I have matches what it had been when initially created (I'm not sure if that actually matters tbh...).
The output I get from the prints are these
ADDR OF PTR: 0x10
SIZE OF BUFFER: 64004
(now inside create_record)
ADDR OF PTR: 0x10
SIZE OF KEY: 4
Can anyone tell me where I'm going wrong?
Thanks in advance
rec doesn't point to any allocated memory. Dereferencing it yields undefined behavior. Already the line's
char* ptr = rec->buffer;
result is undefined.
Instead of the pointer, just define
record rec;
and initialize ptr like
char* ptr = rec.buffer;
I have two pointers. A char pointer with the string "test", and a void pointer.
I'm trying to have pointer point to the address of string.
Here's my code:
#include <stdio.h>
int main(){
void *pointer = NULL;
char *string = "test";
*(char*)pointer = &string;
printf("The string address: %p\n", string);
printf("The string: %s\n", string);
printf("The pointer address: %p\n", pointer);
printf("The pointer points to: %p", *(char*)pointer);
return 0;
}
When I set pointer to be equal to the address of string on line 6 I get makes integer from pointer without a cast. How can I do this?
Edit:
I was printing the wrong addresses. I meant for the printf lines to look like this:
#include <stdio.h>
int main(){
void *pointer = NULL;
char *string = "test";
pointer = &string;
printf("The string address: %p\n", &string);
printf("The string: %s\n", string);
printf("The pointer address: %p\n", &pointer);
printf("The pointer points to: %p", pointer);
return 0;
}
It now properly prints out this:
The string address: 0028FF18 The string: test The pointer address:
0028FF1C The pointer points to: 0028FF18
So string and pointer are separate pointers and pointer points to string.
Why not simply do
#include <stdio.h>
int main(){
void *pointer = NULL;
char *string = "test";
pointer = &string; // point to the address of string
printf("The string address: %p\n", string);
printf("The string: %s\n", string);
printf("The pointer address: %p\n", pointer);
printf("The pointer points to: %p\n", (char*)(*(char**)(pointer)));
return 0;
}
If you want to point pointer at the string addressed by string,
pointer = string;
works.
If you want to point pointer at string,
pointer = &string;
is sufficient.
What you actually are doing is casting pointer to char*, and assigning through it, which is undefined behavior as pointer is NULL.
Actually, conversion from &string to char probably does not work either.
void *pointer = NULL;
pointer here is a pointer of type void. You need to first make sure that this pointer points to some valid memory location before dereferencing it.
Like
pointer = string;
PS: Here string is a string literal so it is read-only if you try to write to this memory location you might get segmentation fault.
If you want to have a pointer that points to the char pointer string, then you should do this:
pointer = &string
If you want to have a pointer that points to the string "test", then you should do this:
pointer = string