I have been having difficulties getting a useable shared memory region in a sample C program (RHEL 6). It should be quite basic so I'm not sure what I'm doing wrong but when I allocate the memory region it appears to be accessible initially. However, when I return from an initialization function the memory region is no longer accessible and I get a segfault when I try to access the memory region.
I have tried running it through GDB and all I see is a segfault on the line where I try to do this memcpy:
memcpy(ptr, &x, sizeof(x));
It's probably something minor that I just cannot see for some reason! Thanks.
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <stdio.h>
#include <sys/sem.h>
#include <sys/shm.h>
#include <sys/stat.h>
#include <errno.h>
void* shared_mem[2];
int init(int *memAddress);
int main() {
if(init((int*)&shared_mem[0]) < 0) {
printf("Error initializing, exiting\n");
exit(1);
}
int *ptr=shared_mem[0];
int x=278;
memcpy(ptr, &x, sizeof(x));
printf("data written to memAddress: %d\n", shared_mem[0]);
}
// Initialize shared memory region and insert test data
int init(int *memAddress) {
key_t key = 234324;
int size = sizeof(int);
static const unsigned int flags = S_IRUSR | S_IWUSR | S_IRGRP |
S_IWGRP | S_IROTH | S_IWOTH | IPC_CREAT;
int id = shmget(key, size, flags);
if (id < 0)
{
return(-3);
}
*memAddress = shmat(id,0,0);
if ((int)memAddress == -1)
{
return(-4);
}
int z=123;
memcpy(memAddress, &z, sizeof(z));
printf("data written to memAddress: %d\n", memAddress[0]);
return(0);
}
Something is completely wrong here and it begins with the following line:
int init(int *memAddress)
You pass a pointer to shared_mem to the function "init". Therefore memAddress will point to the 8- or 16-byte (depending on the CPU type) array shared_mem.
*memAddress = shmat(id,0,0);
If sizeof(void *) == sizeof(int) this would work however then you'd have to do other pointer casts. shared_mem[0] will contain a pointer to the memory, casted to int.
If sizeof(void *) != sizeof(int) you'll already have problems here.
(int)memAddress == -1
This will not work in any case:
(int)memAddress is the address of the array shared_mem and not the value returned by shmat.
memcpy(memAddress, &z, sizeof(z));
This will write the value 123 into shared_mem[0]. Therefore the following instruction:
memcpy(ptr, &x, sizeof(x));
... will be equal to:
memcpy((void *)123, &x, sizeof(x));
... which will cause the error.
The correct function would look like this:
int init(void **memAddress) { // void **
...
*memAddress = shmat(id,0,0); // This was correct!
if ((int)(*memAddress) == -1) // Note the "*"
...
memcpy(*memAddress, &z, sizeof(z)); // Note the "*"
}
Your init function isn't modifiying shared_mem with the allocated memory address - the parameter to init() needs to be declared as int **memaddress for example look at your line *memaddress=shmget(...) with parameter defined as int *memaddress this is storing the result of shmget as an integer, that isn't right. You need to check all the related uses of memaddress are correct. You can check this in gdb, look at the result of shmget, make sure that is being stored in shared_mem[0].
Related
I'm trying to use the brk() function in a C program. My goal is to use it directly (as part of a larger test) by checking the current program break (pb) with
void *current_break = sbrk(0);
executing a malloc (for testing as malloc should sometimes execute brk if the allocated space is large enough)
void* mallow_return = malloc(1);
and than directly executing brk() by using the current address + an increment (and check if this increase the pb):
int increase = 0x01;
void * newbreak = current_break + increase;
int return_value = brk(&newbreak);
My problem is, that neither with a large malloc (malloc(5000;)) nor with (aligned or unaligned) brk() call the pb is changed. When checking the errno I get a
Cannot allocate memory!error (as given bystrerror(errno)
Can anybody see why I'm not able to increase the program break in anyway?
Thanks for any hints!
(System is: Debian 10 (buster) with kernel 4.19)
Edit: As requested this is the main function with includes:
#include <unistd.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <stdlib.h>
void main(int argc, char **argv)
{
printf("[+] Get current program break\n");
void *current_break = sbrk(0);
printf("\t[+] Current break point=\t%#x\n", current_break);
printf("[+] Malloc should call brk as well\n");
void* mallow_return = malloc(1);
printf("[+] Check if malloc changes PB\n");
void *after_break = sbrk(0);
printf("\t[+] After malloc pbreak=\t%#x\n", after_break);
int increase = 0x01;
printf("\t[+] Increasing p-break direclyby %d\n", increase);
void * newbreak = current_break + increase;
printf("\t[+] Setting break point to=\t%#x\n", newbreak);
int return_value = brk(&newbreak);
//check if error was thrown
int errornumber = errno;
if (errornumber != 0)
{
printf("\t[+] Error: %s!\n", strerror(errornumber));
return -1;
}
//check if pb was set now
printf("\t[?] New program break value?\t%#x\n", sbrk(0));
printf("[?] Return value of brk: %d\n", return_value);
return;
}
(Thanks to #Antii Haapala, who posted this as a comment.)
We need to remove the ampersand here:
int return_value = brk(&newbreak);
That line should be simply
int return_value = brk(newbreak);
having some trouble finding out the syntax around returning a vector from a pthread function. Here's currently what I have:
typedef struct vectorData {
vector v1;
vector v2;
} vectorData;
void *vectorAddThread(void *arg) {
vectorData *data = (vectorData *)arg;
vector v1 = data->v1;
vector v2 = data->v2;
vector result = {v1->x + v2->x, v1->y + v2->y, v1->z + v2->z};
return (void*) result;
}
I'm getting errors on the last two lines about the return result, and the the adding part. Thanks
You can't convert a struct to a void * pointer. You need dynamically allocate a vector in your case with malloc, and return the pointer.
vector *result = malloc(sizeof(vector));
result->x = ?;
result->y = ?;
result->z = ?;
return (void *)result;
Now that would solve the issue of returning a struct from a function that returns void *. But if you're using pthreads you shouldn't be returning objects from them, you need to pass the vector to it as user data in arg.
This is probably easiest:
typedef struct vectorData {
vector v1;
vector v2;
vector result;
} vectorData;
Saves messing about with dubious thread-stack vars, mallocs etc. and ties the result output directly to the inputs.
The thread start function in pthread library returns a pointer to void. Can return any pointer type by type-casting it to (void *). The return value can be accessed by pthread_join(3).
However, a vector needs the type of element information also. Not sure if type-casting it to (void *) and accessing it again will work fine. Using it as an element of structure seems better.
In the following example, I am returning a pointer to structure from the thread start function. The structure contains a vector and two character arrays. You can change it according to your requirement. I am using two pointers to show that data is copied on the variable used for pthread_join(3).
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <pthread.h>
#include <errno.h>
#include <vector>
void *functionPthread(void *);
struct retStruct
{
std::vector<int> vecNumber;
char name[20];
char city[20];
};
struct retStruct *r2;
struct retStruct *r1;
int main()
{
int rc, i;
pthread_t th;
r2 = (retStruct*) malloc(sizeof(retStruct));
memset(r2, '\0', sizeof(r2));
if(rc = pthread_create(&th, NULL, &functionPthread, NULL))
{
printf("Thread creation failed, return code %d, errno %d", rc, errno);
}
pthread_join(th, (void**)&r2);
for(i = 0; i < r2->vecNumber.size(); i++)
printf("Vectore element at index %d = %d\n", i, r2->vecNumber.at(i));
printf("Name: %s, City: %s, Vector Number: %d\n", r2->name, r2->city, r2->vecNumber.front());
free(r1);
free(r2);
return 0;
}
void *functionPthread(void *)
{
r1 = (retStruct*) malloc(sizeof(retStruct));
memset(r1, '\0', sizeof(r1));
strcpy(r1->name, "xxxx");
strcpy(r1->city, "yyyy");
r1->vecNumber.push_back(11);
r1->vecNumber.push_back(12);
return r1;
}
For example, If my program segaults, instead of gcc printing to the console "Segmentation Fault" can I have it print "Ya dun goofed"?
Segfaults are generally caused by dereferencing a garbage pointer. Therefore, while the literal answer to what you asked is that, as kaylum said, you can catch SIGSEGV in a signal handler, the better answer is that, before you use a pointer, you should ask yourself, “How do I know that this pointer is valid and that I am staying within the bounds of my array?"
If you don’t know that, your program has a bug. If you think you do, you can turn the assumption into an assertion which, since your pointer is valid, will always pass. For example:
void fill_array( unsigned fill_this_many,
size_t array_size,
int a[array_size] )
{
assert(a);
assert( array_size >= fill_this_many );
for ( unsigned i = 0; i < fill_this_many; ++i )
a[i] = f(i);
return;
}
You’ll now get a detailed message when you’re about to dereference a null pointer or write past the end of your array, which will contain more useful information for debugging than, "There was a segfault somewhere," and it might even save you from silent memory corruption too.
If you want to write your own message, you can define a wrapper such as:
#include <stdio.h>
#include <stdlib.h>
void fatal_error_helper( const char* file, int line, const char* restrict message )
{
fflush(stdout); // Don’t cross the streams!
fprintf( stderr, "\nError in %s, line %d: %s\n", file, line, message );
exit(EXIT_FAILURE);
}
#define fatal_error(message) fatal_error_helper( __FILE__, __LINE__, (message) )
int main(void)
{
int *big_array = calloc( 1073741824UL, sizeof(int) );
if (!big_array)
fatal_error("Not enough memory.");
return EXIT_SUCCESS;
}
And a contrived example of how to do bounds-checking at compile time, so as to fail gracefully if your constants change:
#include <assert.h>
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#define LENGTH 14U
#define M 5U
int main(void)
{
char message[LENGTH] = "hello, world!";
static_assert( M < LENGTH, "Tried to capitalize more letters than the array can hold." );
for ( unsigned i = 0; i < M; ++i )
message[i] = toupper(message[i]);
printf( "%s\n", message );
return EXIT_SUCCESS;
}
#include <signal.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
void segv_handler(int sig)
{
(void)sig;
const char *msg = "Hello signal handler!";
size_t len = strlen(msg);
write(STDERR_FILENO, msg, len);
abort();
}
int main()
{
struct sigaction act;
act.sa_handler = segv_handler;
sigemptyset(&act.sa_mask);
act.sa_flags = 0;
sigaction(SIGSEGV, &act, NULL);
int *nullint = 0;
*nullint = 4;
return 0;
}
EDIT: I tough code is pretty much explanation how to do it. Of course there is a lot details that needs to be taken into account when writing signal handlers.
Basic limitation is that signal handler can't access any variable/structure that isn't written to atomically because handler could be called between any two instructions in your program. That means no calls to heap memory management, buffered io like printf, etc.
More details what the code does can be found from man pages stdout, sigaction and write.
I'm fully prepared to be told that I'm doing something stupid/wrong; this is what I expect.
I'm getting a feel for structures and coming a cropper when it comes to accessing the fields from the pointers. Code to follow.
matrix.h:
#ifndef MATRIX_H_INCLUDED
#define MATRIX_H_INCLUDED
#include <stdlib.h>
typedef struct
{
size_t size;
int* vector;
} vector_t;
#endif // MATRIX_H_INCLUDED
main.c:
#include <stdio.h>
#include <stdlib.h>
#include "matrix.h"
vector_t* vector_new(size_t size)
{
int vector[size];
vector_t v;
v.size = size;
v.vector = vector;
return &v;
}
int main(int argc, char* argv[])
{
vector_t* vec = vector_new(3);
printf("v has size %d.\n", vec->size);
printf("v has size %d.\n", vec->size);
return EXIT_SUCCESS;
}
So this is a very simple program where I create a vector structure of size 3, return the pointer to the structure and then print its size. This, on the first print instance is 3 which then changes to 2686668 on the next print. What is going on?
Thanks in advance.
You are returning a pointer to a local variable v from vector_new. This does not have a slightest chance to work. By the time vector_new returns to main, all local variables are destroyed and your pointer points to nowhere. Moreover, the memory v.vector points to is also a local array vector. It is also destroyed when vector_new returns.
This is why you see garbage printed by your printf.
Your code has to be completely redesigned with regard to memory management. The actual array has to be allocated dynamically, using malloc. The vector_t object itself might be allocated dynamically or might be declared as a local variable in main and passed to vector_new for initialization. (Which approach you want to follow is up to you).
For example, if we decide to do everything using dynamic allocation, then it might look as follows
vector_t* vector_new(size_t size)
{
vector_t* v = malloc(sizeof *v);
v->size = size;
v->vector = malloc(v->size * sizeof *v->vector);
return v;
}
(and don't forget to check that malloc succeeded).
However, everything that we allocated dynamically we have to deallocate later using free. So, you will have to write a vector_free function for that purpose.
Complete re-write of answer to address your question, and to provide alternate approach:
The code as written in OP will not compile: &v is an illegal return value.
If I modify your code as such:
#include <stdlib.h>
#include <stdio.h>
#include <stdlib.h>
typedef struct
{
size_t size;
int* vector;
} vector_t;
vector_t* vector_new(size_t size)
{
int vector[size];
vector_t v, *pV;
pV = &v;
pV->size = size;
pV->vector = vector;
return pV;
}
int main(int argc, char* argv[])
{
vector_t* vec = vector_new(3);
printf("v has size %d.\n", vec->size);
printf("v has size %d.\n", vec->size);
getchar();
return EXIT_SUCCESS;
}
It builds and runs, but returns unintended values for vec->size in main() due to the local scope of that variable in the function vector_new.
Recommend creating globally visible instance of your struct, and redefine vector_new() to int initVector(void):
#include <stdlib.h>
#include <stdio.h>
#include <stdlib.h>
#define SIZE 10
typedef struct
{
size_t size;
int* vector;
} vector_t;
vector_t v, *pV;//globally visible instance of struct
int initVector(void)
{
int i;
pV->size = SIZE;
pV->vector = calloc(SIZE, sizeof(int));
if(!pV->vector) return -1;
for(i=0;i<SIZE;i++)
{
pV->vector[i] = i;
}
return 0;
}
int main(int argc, char* argv[])
{
int i;
pV = &v; //initialize instance of struct
if(initVector() == 0)
{
printf("pV->size has size %d.\n", pV->size);
for(i=0;i<SIZE;i++) printf("pV->vector[%d] == %d.\n", i, pV->vector[i]);
}
getchar(); //to pause execution
return EXIT_SUCCESS;
}
Yields these results:
You still need to write a freeVector function to undo all the allocated memory.
I am going to use GLib's Hash table implementation in a C program and just for now
I am just experimenting with it. I wrote the following piece of code for testing:
#include <glib.h>
#include <stdlib.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>
int main(){
// Some codes and declerations here
GHashTable *g_hash_table;
uint32_t *a;
a=(uint32_t *)malloc(sizeof(uint32_t));
if(a==NULL){
printf("Not Enough Mem For a\n");
return 1;
}
*a=1123231;
uint32_t* key;
key=(uint32_t *)malloc(sizeof(uint32_t));
if(key==NULL){
printf("Not Enough Mem For key\n");
return 1;
}
*key=122312312;
int i;
g_hash_table=g_hash_table_new(g_int_hash, g_int_equal);
for(i=0;i<TABLE_SIZE;i++){
*key+=1;
*a+=1;
g_hash_table_insert(g_hash_table,(gpointer)key,(gpointer)a);
uint32_t *x=(uint32_t *)g_hash_table_lookup(g_hash_table,key);
printf("Counter:%d, %u\n",i,*x);
}
GHashTableIter iter;
g_hash_table_iter_init(&iter,g_hash_table);
int size=g_hash_table_size(g_hash_table);
printf("First size: %d\n",size);
uint32_t *val;
uint32_t *key_;
int counter=0;
// My problem is in the following loop it
// always returns the same and the last key value pair
while(g_hash_table_iter_next(&iter,(gpointer*)(void*)&key_,(gpointer*)(void*)&val)){
counter++;
printf("%u %u\n",(uint32_t)*key_,(uint32_t)*val);
printf("Counter: %d\n",counter);
}
//Some more code here
return 0;
}
Somehow my test code iterates correctly but in the loop it always returns the last key and last value pairs and it is always the same. What is the problem here? The above code may not run with its as it is format. I just copied and pasted some parts to give a clear idea about what I am trying to do.
I think your insertion code is broken. You're only allocating memory once, but then doing many inserts, incrementing the value stored in the single allocated location between each.
The hash table stores your pointer, so it will end up associating each key with the same pointer.
Also, you should probably use g_malloc() with glib, for consistency.
And I always recommend using sizeof on objects rather than on their types; that way you don't repeat yourself in quite as dangerous a way. So, instead of
guint32 *a;
a = g_malloc(sizeof (guint32));
use
a = g_malloc(sizeof *a);
This way you "lock down" the dependency, so that you always allocate enough room to store whatever a points at, even if you later change the type.
Further, you should take a hard look at every cast you do. Casting any non-constant pointer to gpointer is a sign of a hesitant programmer. With glib, gpointer is just a synonym for void *, so that cast is never needed. It just adds cruft to your code, making it harder to read.
There is an error in key, a declarations. You always put the same pointer in the hash table. Try:
#include <glib.h>
#include <stdlib.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#define TABLE_SIZE 12
int main() {
// Some codes and declarations here
GHashTable *g_hash_table;
int i;
g_hash_table = g_hash_table_new(g_int_hash, g_int_equal);
for (i=0; i<TABLE_SIZE; i++)
{
uint32_t* key = (uint32_t *)malloc(sizeof(uint32_t));
uint32_t* a = (uint32_t *)malloc(sizeof(uint32_t));
*key = i;
*a = i+10;
g_hash_table_insert(g_hash_table, (gpointer)key, (gpointer)a);
uint32_t *x = (uint32_t *)g_hash_table_lookup(g_hash_table,key);
printf("key: %d --> %u\n", *key ,*x);
}
GHashTableIter iter;
int size=g_hash_table_size(g_hash_table);
printf("First size: %d\n", size);
uint32_t *val;
uint32_t *key_;
// My problem is in the following loop
// it always returns the same and the last key value pair
g_hash_table_iter_init (&iter, g_hash_table);
while (g_hash_table_iter_next (&iter, (gpointer) &key_, (gpointer) &val))
{
printf("key %u ---> %u\n", (uint32_t)*key_, (uint32_t)*val);
}
// TODO: free keys
return 0;
}