Not quite sure, segfault on memcpy? - c

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;

Related

Memory allocation issue with fortran and C program

I have a fortran code that I am trying to get to work for my research purposes. The fortran code passes an integer variable and an integer size into a C program that will allocate memory. The code consists of a pointer "iarrays" that point to "arrays(1)". I get a segmentation fault with the following message:
Segmentation Fault
The following is the fortran Code:
subroutine initmem
c-----initial memory setup
pointer ( iarrays , arrays(1) )
c-----allocate pointer memory for blocks and set blocks index pointers
lpoint(0,1) = 0
c-----first call to lpoinst computes storage requirements
call lpoinst
c-----Returns kplast = 1138280 which is the No. of bytes for pointered arrays. I have verified lpoinst works correctly
nwdinc = kplast - lpoint(0,1)
Array lpoint after lpoinst function
c-----nbytaddr = 1
call getmem (lpoint(0,1), (nwdinc*nbytaddr))
c-----Note:getmem is a fortran file only used to check if memory is allocated. I have not included the code in this post.
c-----getmem.F calls C program memalloc(lpoint(0,1), (nwdinc*nbytaddr))
c-----memalloc.c code attached below
c-----value of lpoint(0,1) = -1431465968
c-----second call to lpoinst sets pointers with updated lpoint(0,1).
call lpoinst
Array lpoint after lpoint(0,1) was updated
iarrays = lpoint(0,1)
isize = nwdinc / addrinc
do 100 i=1,isize
arrays(i) = zero
100 continue
return
end
Here is the C program memalloc.c:
#include <stdio.h>
#include <fcntl.h>
#include <stdlib.h>
#ifdef _CRAY
int MEMALLOC (nextptr, size)
#else
#ifdef POST_UNDERSCORE
int memalloc_ (nextptr, size)
#else
int memalloc (nextptr, size)
#endif
#endif
int *size;
int *nextptr;
{
void *ptr;
printf("Size Address:%d Size Value: %d \n", size, *size);
printf("nextptr Address:%d nextptr Value: %d \n", nextptr, *nextptr);
printf("ptr before hexa: %p ptr before int: %d \n", (void *) ptr, (int *) ptr );
if (*nextptr == NULL) {
if ((ptr = (void *) malloc (*size)) == NULL) {
return(-1);
}
}
else {
if ((ptr = (void *) realloc (*nextptr, *size)) == NULL) {
return(-1);
}
}
printf("ptr after hexa: %p ptr after int: %d \n", (void *) ptr, (int *) ptr );
*nextptr = (int) ptr;
printf("nextptr Address:%d nextptr Value: %d \n", nextptr, *nextptr);
return (0);
}
Print statements in memalloc.c
The pointer iarrays is set to a negative value. Can the value of that pointer be negative? Why is not able to access the memory for arrays(i)? Can someone help me get through this segmentation fault?
Thank you!

Getting char array value from a method by using pointer.

I have been trying to get the following to work:
My goal is to use pointers in main() to access elements created in a method().
// takes in address of pointer
int method(char** input) {
char *buffer = malloc(sizeof(char)*10);
buffer[0] = 0x12;
buffer[1] = 0x34;
buffer[2] = 0xab;
*input = & buffer;
printf("%x\n", *buffer); // this prints 0x12
printf("%x\n", &buffer); // this prints address of buffer example: 0x7fffbd98bf78
printf("%x\n", *input); // this prints address of buffer
return 0;
}
int main(){
char *ptr;
method(&ptr);
printf(%p\n", ptr); // this prints address of buffer
//this does not seem to print out buffer[0]
printf(%x\n", *ptr);
}
I want to print each element of buffer values, as created by the method() by using ptr. Any suggestions on how I can go about doing this?
I am not sure if I am misunderstanding something, but I thought ptr points to address of buffer. Thus, dereferencing would give me buffer[0]?
Thank you.
This a fixed & commented version of your code. Ask in the comments if there is smth. you don't understand.
#include <stdio.h>
#include <stdlib.h>
// takes in address of pointer
//Hex: 0xab is larger than the max value of a signed char.
//Most comilers default to signed char if you don't specify unsigned.
//So you need to use unsigned for the values you chose
int method(unsigned char** input) { //<<< changed
unsigned char *buffer = malloc(sizeof(char)*10);
//Check for malloc success <<< added
if(!buffer)
exit(EXIT_FAILURE);
buffer[0] = 0x12;
buffer[1] = 0x34;
buffer[2] = 0xab;
//I recommend not to mix array notation and pointer notation on the same object.
//Alternatively, you could write:
*buffer = 0x12;
*(buffer + 1) = 0x34;
*(buffer + 2) = 0xab;
//buffer already contains the address of your "array".
//You don't want the address of that address
*input = buffer; //<<< changed (removed &)
printf("%x\n", *buffer); // this prints 0x12
//Not casting &buffer will likely work (with compiler warnings
//But it is better to conform. Either use (char *) or (void *)
//<<< added the cast for printf()
printf("%p\n", (char *)&buffer); // this prints address of buffer example: 0x7fffbd98bf78
printf("%p\n", *input); // this prints address of buffer
return 0;
}
int main(){
unsigned char *ptr;
method(&ptr);
printf("%p\n", ptr); // this prints address of buffer
//this does not seem to print out buffer[0]
for(int i = 0; i < 3; i++){
//<<< changed to obtain content of buffer via ptr for loop.
unsigned char buf_elem = *(ptr + i);
printf("buffer[%d] in hex: %x\t in decimal: %d\n", i, buf_elem, buf_elem);
}
// Don't forget to free the memory. //<<< changed
free(ptr);
}

How to assign string into char* pointer?

#include <stdio.h>
struct Analysis {
int lnlen;
int arr[2];
char* name;
};
int main()
{
struct Analysis ana_space[2];
char *ptr = (void*) &ana_space;
ana_space[0].lnlen = 0;
ana_space[0].arr[0] = 1;
ana_space[0].arr[1] = 2;
ana_space[0].name = "Peter";
printf("\n%d\n", *ptr); // print 0;
*ptr = 10; // how to use memcpy here;
printf("\n%d\n", *ptr); // print 10;
ptr = ptr + sizeof(int); // advance pointer by int;
printf("\n%d\n", *ptr); // print 1;
ptr = ptr + 2*sizeof(int); // advance pointer by 2 ints;
printf("\n%s\n", *ptr); // print "Peter"; --------------not work
//*ptr = "Jim"; // how to assign new name "Jim" into that memory;
return 0;
}
Output:
0
10
1
(null)
I want to use char * as pointer to go through memory address to get some data and also store value into memory.
For int and int array, it works fine, but not for the string.
How to print the string and store new string value into memory?
Your approach is not portable. It will be better to use offsetof to make sure that you can reliably point to the addresses of the members of a struct.
int main()
{
struct Analysis ana_space[2];
char *ptr = (void*) &ana_space;
size_t offset1 = offsetof(struct Analysis, arr);
size_t offset2 = offsetof(struct Analysis, name);
ana_space[0].lnlen = 0;
ana_space[0].arr[0] = 1;
ana_space[0].arr[1] = 2;
ana_space[0].name = "Peter";
// advance pointer to point to arr.
ptr = ptr + offset1;
// advance pointer to point to name
ptr = ptr + (offset2-offset1);
// Cast the pointer appropriately before dereferencing.
printf("\n%s\n", *(char**)ptr);
// how to assign new name "Jim" into that memory;
*(char**)ptr = "Jim";
printf("\n%s\n", *(char**)ptr);
return 0;
}
Your use of:
printf("\n%d\n", *ptr); // print 0;
*ptr = 10; // how to use memcpy here;
printf("\n%d\n", *ptr); // print 10;
and the expected output is flawed. It works only with little endian systems. I suggest using:
printf("\n%d\n", *(int*)ptr);
*(int*)ptr = 10;
printf("\n%d\n", *(int*)ptr);
The code you presented could cause undefined behavior due to padding and representations of types, which are implementation-defined.
After you increment the pointer ptr here:
ptr = ptr + 2*sizeof(int);
the pointer ptr points to the member name of the struct Analysis. If you dereference the pointer ptr, you get the type char and thus a single byte. This byte does not represent a pointer to the string.
The pointer ptr will have to be cast to the type pointer to a pointer to char, and then dereferenced so the correct and full value of the member name will be obtained.
That resulting value is a pointer to the string "Peter".
ANSI C has a macro called offsetof() found in stddef.h that gives a more sure way of calculating the pointer offset of a member within a struct. Here, we can get the the address of the name member in ana_space[0] directly.
ptr = (char*) &ana_space + offsetof(struct Analysis, name);
This takes out any guess work on padding.
This pointer then has to be properly cast to print the contents of name:
printf("%s\n", *(char**) ptr);

Casting integers as another char pointer

I'm testing the code below, but the output just says
ptr char = (null)
Any clue why this is happening?
int buf[1024];
buf[0] = 10;
buf[1] = 0;
buf[2] = 1992;
buf[3] = 42;
buf[4] = 5;
char *ptr;
ptr = (char*)buf+2;
printf("ptr char = %s\n",*ptr);
I just experimented on the above code so that I could know part by part what the code below would do.
here is the code I'm working on
int fillNSendHttpReq(int8u seq, char* domain, char* uri, char method, char* contentType, char* otherHeader, int contentLen, char* content, unsigned char timeout, char moreData, char isHttps)
{
int16u encodedLen = moreData?contentLen|0x8000:contentLen;
//if moredata = true then encodelen = contentlenBITWISEOR0x8000
char *ptr = NULL;
int8u buf[1024];
memset(buf, 0, sizeof(buf));
buf[0] = SNIC_HTTP_REQ;
buf[1] = seq;
*((int16u*)&buf[2]) = 0x5000; //swapped
buf[4] = method;
buf[5] = timeout;
if (isHttps) {
buf[0] = SNIC_HTTPS_REQ;//SNIC_HTTPS_REQ = 0
*((int16u*)&buf[2]) = 0xbb01; // 443 swapped
}
ptr = (char*)buf+6; //convert in8u to char * ???
ptr += sprintf(ptr, "%s", domain)+1; //ptr = ptr + strlen(domain)+1
ptr += sprintf(ptr, "%s", uri)+1;
ptr += sprintf(ptr, "%s", contentType)+1;
ptr += sprintf(ptr, "%s", otherHeader)+1;
*((int16u*)ptr) = swap16(encodedLen);
ptr += 2;
if (contentLen)
memcpy(ptr, content, contentLen);
serial_transmit(CMD_ID_SNIC, buf, ptr-(char*)buf+contentLen, ACK_NOT_REQUIRED);
return 0;
the part I don't understand is that ptr-(char*)buf+contentLenwas assigned to the variable defined as int and so that got me confused on where my content went which was a char.
int is of some size. When you add 2 to a char*, the pointer advances by two bytes; to advance it by the size of an int, you’d do (char*)(buf + 2). Two bytes past buf might be buf[1], or it might be half of buf[0], but apparently it points to zero, because that’s what you get by dereferencing ptr later – NULL is 0. When passing a string to printf, you don’t dereference it first.
I don’t really know how to fix that part, though, because it just doesn’t make a lot of sense. If your code is close to your intent, then this is probably what it should be:
char *ptr = (char*)(buf + 2);
printf("ptr char = %s\n", ptr);
in which case it’ll print either zero or one characters with your example buf.
char *ptr;
ptr = (char*)buf+2;
printf("ptr char = %s\n",*ptr);
ptr is a char pointer, so *ptr is the character it points to. You passed a character as parameter while the printf is waiting for a "string" (char pointer) so it crashed
Previously you have assigned ptr = (char*)buf+2; so ptr is now pointing to halfway between buff[0] and buff[1], and *ptr == 0 (since buf[0] = 10;, the third byte in buff is zero regardless of endianness, assuming sizeof(int) >= 4), so it represents a NULL value when printf reads it as a pointer. That's why you see the output
Use this
printf("ptr char = %s\n", ptr);
But then you'll see another empty output since ptr[0] is now '\0'

Arrays and pointer : segmentation fault

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);

Resources