After searching through many threads on similar issues, I've been unable to determine why I've been getting a seg fault with my program. I have two files: buffer.c where I create a circular buffer and deposit/remove values from it and a main file where several threads call the operations on the circular buffer with user input. Semaphores are used to prevent concurrent access.
Here are the relevant parts of my main program:
int main (int argc, char const *argv[]) {
st_init();
Buffer *bufferA,*bufferB,*bufferC;
createBuffer(bufferA,128);
createBuffer(bufferB,128);
createBuffer(bufferC,128);
// Create the struct used to initialize threads.
ThreadInit initA = {
bufferA,
bufferA
};
ThreadInit initB = {
bufferA,
bufferB
};
ThreadInit initC = {
bufferB,
bufferC
};
ThreadInit initD = {
bufferC,
bufferC
};
// Create threads
if (st_thread_create(getInputStream, &initA, 0, 0) == NULL) {
perror("Thread a creation failure.");
exit(EXIT_FAILURE);
}
if (st_thread_create(convertCR, &initB, 0, 0) == NULL) {
perror("Thread b creation failure.");
exit(EXIT_FAILURE);
}
if (st_thread_create(squashChar, &initC, 0, 0) == NULL) {
perror("Thread c creation failure.");
exit(EXIT_FAILURE);
}
if (st_thread_create(printOutput, &initD, 0, 0) == NULL) {
perror("Thread d creation failure.");
exit(EXIT_FAILURE);
}
// Exit from main via ST.
st_thread_exit(NULL);
return 0;
}
void *getInputStream(void *state) {
ThreadInit *threadInit = state;
char inputChar = getchar();
while (inputChar != EOF) {
deposit(inputChar, threadInit->produceBuff); //where segfault occurs
inputChar = getchar();
st_usleep(SLEEP_TIME);
}
st_thread_exit(NULL);
}
and buffer.c
void createBuffer(Buffer *buff, int buffSize){
buff = (Buffer*) calloc(1, sizeof(Buffer));
semaphore mutex,emptyBuffers,fullBuffers;
buff->mutex = calloc(1,sizeof(semaphore));
buff->emptyBuffers = calloc(1,sizeof(semaphore));
buff->fullBuffers = calloc(1,sizeof(semaphore));
createSem(buff->mutex,1);
createSem(buff->emptyBuffers,buffSize);
createSem(buff->fullBuffers,0);
buff->charBuff = malloc(sizeof(char) * buffSize);
buff->nextIn = 0;
buff->nextOut = 0;
buff->buffSize = buffSize;
}
The seg fault occurs the first time an operation is done on the semaphores in my buffers, which leads me to believe their memory is improperly allocated, though I included the code from my main in case I'm wrong in that assumption. Also, in case it's not clear from my code, I'm quite new to C, so I'd appreciate any guidance. Thanks!
Here is the error
void createBuffer(Buffer *buff, int buffSize){
buff = (Buffer*) calloc(1, sizeof(Buffer));
you need to return the pointer of the buffer otherwise you are not returning the changed pointer to the caller
void createBuffer(Buffer **buff, int buffSize){
*buff = calloc(1, sizeof(Buffer));
a bit simplified : it is similar to
int foo(int a)
{
a = 1; // 1 not visible outside foo
}
and
int foo(int *a)
{
*a = 1; // 1 is visible outside foo
}
also in C you don't cast what is returned from calloc/malloc only if you are compiling with a C++ compiler but then you should use new instead
In c, function parameter is passed by value so your createBuffer() function didn't really create anything; it just leaked memory instead.
One easy fix is to allocate the memory in main():
bufferA = (Buffer*) calloc(1, sizeof(Buffer));
and remove this line:
buff = (Buffer*) calloc(1, sizeof(Buffer));
I don't see how your createSem() is implemented by you may want to check it too.
Related
I have to use a buffer of size max_cache_req_len to read in the value received from mq_receive. Here is my code that is receiving a value from shared memory and then placing it on a queue:
size_t received_bytes = 0;
char buffer[MAX_CACHE_REQUEST_LEN];
received_bytes = 0;
memset(&buffer, 0, MAX_CACHE_REQUEST_LEN);
received_bytes = mq_receive(mq, buffer, MAX_CACHE_REQUEST_LEN, NULL);
if (received_bytes != -1)
{
item_type *item = malloc(sizeof(item_type));
item->path = buffer;
pthread_mutex_lock(&queue_lock);
steque_enqueue(&queue, item);
pthread_cond_signal(&queue_cond);
pthread_mutex_unlock(&queue_lock);
}
Here is my code that is taking the item off the queue, and placing it into a char* value. When I print the path, I get "".
void *worker(void *arg)
{
item_type *new_item;
char *path;
int fd;
while (1)
{
pthread_mutex_lock(&queue_lock);
while (steque_isempty(&queue) == 1)
pthread_cond_wait(&queue_cond, &queue_lock);
new_item = steque_pop(&queue);
path = new_item->path;
free(new_item);
new_item = NULL;
pthread_mutex_unlock(&queue_lock);
fd = simplecache_get(path);
sleep(cache_delay);
printf("%d\n", fd);
printf("%s\n", path);
// MAKE WORKER THREAD TAKE
if (fd == CACHE_FAILURE)
{
}
else
{
}
}
}
If I hardcode something like:
item->path = "buffer";
Then it prints buffer from within my worker function. This is a multithreaded application, I am just unsure what to do with my char[size] array to transform it into a char* and allow it to transfer.
Nutshell:
(char*)&char[size] queued -> queue turns it into a void* -> popped off queue, turned into a char* and value is lost
I've been trying to fix this for 2 days now. I really don't understand what is going on.
I wrote a function to read from a file line per line. It's called get_next_line(). This is a project for school, I'm only allowed to use my own C library and read(), malloc() and free().
Here is a link to the full GitHub repo, including the instructions. I can only submit get_next_line.c and get_next_line.h at the end.
Basically, my program seems to run fine if don't handle memory leaks. When I start fixing leaks by using my ft_strdel() function, my program still runs fine for most test cases.
void ft_strdel(char **as)
{
if (!as || !*as)
return ;
free(*as);
*as = 0;
}
Yet, if I pass it through the advanced unit test we have at school, I have different errors. They seem to appear randomly sometimes as I can pass 3 times in a row and get a malloc error the 4th time.
The current version seems to handle all memory leaks. Thus, I have this error from the filechecker:
get_next_line_tests(43165,0x7fff9e83d340) malloc: *
error for object 0x7fe0e3403748: incorrect checksum for freed object -
object was probably modified after being freed.
* set a breakpoint in malloc_error_break to debug
Here is the full function:
#include "get_next_line.h"
static t_list *get_current_node(const int fd, t_list **line_list)
{
t_list *tmp;
tmp = *line_list;
while (tmp)
{
if ((int)tmp->content_size == fd)
return (tmp);
tmp = tmp->next;
}
return (NULL);
}
static t_list *create_new_node(int fd, t_list **line_list)
{
t_list *new;
new = ft_lstnew("\0", fd);
ft_lstadd(line_list, new);
return (new);
}
char *read_until_newline(int fd)
{
char buf[BUFF_SIZE + 1];
char *tmp;
char *stack;
int ret;
if (read(fd, buf, 0) < 0)
return (NULL);
stack = ft_strnew(1);
if (!stack)
return (NULL);
while ((ret = read(fd, buf, BUFF_SIZE)) > 0)
{
buf[ret] = '\0';
tmp = ft_strjoin(stack, buf);
ft_strdel(&stack);
stack = tmp;
if (ft_strchr(buf, '\n'))
break;
}
return (stack);
}
int get_index_newline(char *str)
{
int i;
i = 0;
while (str[i] && str[i] != '\n')
i++;
return (i);
}
int get_next_line(const int fd, char **line)
{
static t_list *line_list;
t_list *current;
char *buffer;
char *tmp;
int index_newline;
if (fd < 0 || line == NULL)
return (-1);
current = get_current_node(fd, &line_list);
if (!current)
current = create_new_node(fd, &line_list);
if (!ft_strchr(current->content, '\n'))
buffer = read_until_newline(fd);
else
buffer = ft_strnew(1);
if (!buffer)
return (-1);
if (!ft_strlen(buffer) && !ft_strlen(current->content))
return (0);
tmp = current->content;
current->content = ft_strjoin(tmp, buffer);
if (tmp)
ft_strdel(&tmp);
if (buffer)
ft_strdel(&buffer);
index_newline = get_index_newline(current->content);
*line = ft_strsub(current->content, 0, index_newline);
tmp = current->content;
current->content = ft_strsub(tmp, index_newline + 1, ft_strlen(tmp) - index_newline - 1);
if (tmp)
ft_strdel(&tmp);
return (1);
}
Feel free to comment on any beginner error I could be doing in my code. Please note however that I have to follow a certain norm, that explain my variable declarations and initializations. I cannot use for loops. And have many restrictions like those.
Protecting my ft_strdel() calls with if statements was my last attent at solving the issue, obviously it failed and it's useless.
EDIT:
I handle multiple fd by using a static linked list. Each node contains a string with the last read buffer (whatever is left from the reading after substracting the most recently read line). And each node contains an int to store the fd it was read from. This way, I loop through the list until I find the corresponding fd to check for preexisting reading. If no node is returned, it means I have nothing stored for the specific fd so I'll just create a new node.
I hope you have answers! I'm not a regular user on Stack Overflow, I did my best to format my post and be specific. Tell me if I need to edit something.
And thanks for your help!
I have this function. As you can see, everything is being done in the function, I'm not allocating in the main and then passing anything to it (I'll only return the pointer to the array once the function is done). The function in itself (with a fixed size for the array) works, but the realloc fails.
struct database *parse() {
int i = 0;
int n = 1;
FILE *dbase = (fopen(PATH, "r"));
if (dbase == NULL) {
fprintf(stderr, ERRORE_APERTURA);
exit(EXIT_FAILURE);
}
struct database *database_array = calloc(20*n, sizeof(struct database));
if (database_array == NULL) {
fprintf(stderr, "Impossibile allocare memoria\n");
exit(EXIT_FAILURE);
}
while (feof(dbase) == 0) {
fscanf(dbase, "%[^:]:%[^:]:\n", database_array[i].user, database_array[i].password);
database_array[i].iswritten = 1;
i++;
if (i > 20*n) {
n++;
struct database *new_database_array = realloc(database_array, sizeof(struct database)*(20*n));
database_array = new_database_array;
}
}
database_array[++i].iswritten = 0;
fclose(dbase);
return database_array;
}
I tried reading other explanations, but I can't understand what's wrong here.
The array I allocated with calloc is initially 20. then, when it's filled, I want it to double in size, so I use n, which will be 2, by 20, so 40.
The frustrating thing is that I tried reallocating an array of struct with a simpler program, and doing THE SAME THING works without any problem:
#include <stdio.h>
#include <stdlib.h>
struct prova {
int a;
int b[10];
};
int main() {
struct prova* array_struct = calloc(10, sizeof(struct prova));
array_struct[0].a = 2;
struct prova* tmp = realloc(array_struct, sizeof(struct prova) * 20);
free(array_struct);
array_struct = tmp;
array_struct[1].b[1] = 3;
printf("a = %d", array_struct[0].a);
printf("b = %d\n", array_struct[1].b[1]);
return 0;
}
What am I not seeing? (Please nevermind the fact that I'm not checking if realloc returns NULL, I'll add that later)
struct database *new_database_array = realloc(database_array, sizeof(struct database)*(20*n));
free(database_array);
You can't both reallocate something and deallocate it. You can do either, but once you've done either, the previous allocation no longer exists, so you can't do the other.
After the first line of code above, the value of database_array should not be used anymore because it may not be valid.
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 8 years ago.
Improve this question
I'm trying to access a pointer inside of a struct, I tried placing * in front of the struct pointer
to access the pointer inside the struct, but it segfaults.
code segfaults on *ptr->numberOfClients = clients;
int getNumberOfClients(struct fuzzerObj *ptr)
{
int rtrn;
long clients;
char *input;
char *holder = NULL;
printf(BOLDBLUE"How many clients will you be connecting to this fuzz server?\n"RESET);
printf(BOLDBLUE"---> "RESET);
rtrn = getUserInput(&input);
if(rtrn < 0)
{
errorHandler("Can't Get User input\n", FUNCTION_ID_GET_NUMBER_OF_CLIENTS);
return -1;
}
if (strlen(input))
{
clients = strtol(input, &holder, 10);
if (input == holder)
{
errorHandler("invalid long conversion\n", FUNCTION_ID_GET_NUMBER_OF_CLIENTS);
return -1;
}
}
else
{
errorHandler("No Value To Compute\n", FUNCTION_ID_GET_NUMBER_OF_CLIENTS);
return -1;
}
*ptr->numberOfClients = clients;
free(input);
return 0;
}
int getUserInput(char **buf)
{
int i = 0, max = 1024, c;
*buf = reallocarray(NULL, 1025, sizeof(char *));
if(*buf == NULL)
{
errorHandler("Mem Error\n", FUNCTION_ID_GET_USER_INPUT);
free(*buf);
return -1;
}
while (true) { // skip leading whitespace
c = getchar();
if (c == EOF) break; // end of file
if (!isspace(c)) {
ungetc(c, stdin);
break;
}
}
while (true) {
c = getchar();
if (isspace(c) || c == EOF) // at end, add terminating zero
buf[i] = 0;
break;
}
*buf[i] = c;
if (i==max-1) { // buffer full
max = max+max;
*buf = (char*)realloc(*buf,max); // get a new and larger buffer
if (buf == 0)
{
errorHandler("Realloc Error\n", FUNCTION_ID_GET_USER_INPUT);
return -1;
}
}
i++;
return 0;
}
and here's the struct
struct fuzzerObj
{
int parserResponse;
int *numberOfClients;
int *clientFuzzerType[1024];
int *clientSockets[1024];
int *clientApplication[1024];
int *clientFuzzer[1024];
int *connectedClients;
int *socket;
int *fuzzer;
int *application;
dispatch_queue_t queue;
};
There is a major problem that I see (unless you've not shown it in your code snippets). numberOfClients is declared as such:
struct fuzzerObj
{
...
int *numberOfClients;
...
};
Before you assign an int to it. You must assign memory to store the int:
1.
ptr->numberOfClients = malloc(sizeof(*(ptr->numberOfClients)));
*(ptr->numberOfClients) = clients;
...
free(ptr->numberOfClients);
2.
int temp;
ptr->numberOfClients = &temp;
*(ptr->numberOfClients) = clients;
...
// Write to a file here???
Another question... why are the fields of fuzzerObj pointers? If you make them ints instead of pointers to ints, you wouldn't have the difficulties you're experiencing.
EDIT
The second method shown above is not safe because once the function that has declared temp returns, temp no longer exists, and therefore numberOfClients doesn't have valid memory, and should not be used.
It is totally unclear why data member numberOfClients defined as a pointer instead of to be an object of type int
int *numberOfClients;
Try the following
ptr->numberOfClients = ( int * )malloc( sizeof( int ) );
if ( ptr->numberOfClients ) *ptr->numberOfClients = clients;
Also take into account that variable clients is defined as
long clients;
In some implementations sizeof( lomg ) can be greater than sizeof( int ).
It is in general a bad design. It is unclear whether data members of the structures were initialized and corresponding memory were allocated.
Could someone check my code and tell me if I am on the right track.. It seems like I am a bit lost.. if you see my errors, please let me know them..
What I am trying to do is to solve bounded buffer using my own semaphores as well as GCD.
Thanks in advance..
sema.c
void procure( Semaphore *semaphore ) {
pthread_mutex_lock(semaphore->mutex1);
while(semaphore->value <= 0)
pthread_cond_wait(&semaphore->condition, semaphore->mutex1);
semaphore->value--;
pthread_mutex_unlock(semaphore->mutex1);
}
void vacate( Semaphore *semaphore ) {
pthread_mutex_lock(semaphore->mutex1);
semaphore->value++;
pthread_cond_signal(&semaphore->condition);
pthread_mutex_unlock(semaphore->mutex1);
}
void init ( Semaphore *semaphore ){
semaphore->value = 1;
pthread_mutex_t myMutex;
semaphore->mutex1 = &myMutex;
pthread_mutex_init( semaphore->mutex1, NULL);
}
void destroy ( Semaphore *semaphore ) {
pthread_mutex_destroy(semaphore->mutex1);
}
and main.c
struct variables {
Semaphore *sem;
};
struct variables vars;
void constructer (int *buffer, int *in, int *out) {
init(vars.sem);
}
void deconstructer () {
destroy(vars.sem);
}
int rand_num_gen() {
uint_fast16_t buffer;
int file;
int *rand;
file = open("/dev/random", O_RDONLY);
while( 1 ) {
read(file, &buffer, sizeof(buffer));
printf("16 bit number: %hu\n", buffer );
*rand = (int) buffer;
close(file);
break;
}
return *rand;
}
void put_buffer( int* buffer, int* in, int* out ) {
buffer[*in] = rand_num_gen(); // produce
procure(vars.sem); // wait here
*in = (*in + 1) % BUF_SIZE;
vacate(vars.sem);
}
void get_buffer( int* buffer, int* in, int* out ) {
int value;
procure(vars.sem);
value = buffer[*out];
vacate(vars.sem);
*out = (*out + 1) % BUF_SIZE;
}
int main (void) {
int *in, *out, *buffer;
constructer(buffer, in, out);
dispatch_queue_t producer, consumer;
producer = dispatch_queue_create("put_buffer", NULL);
consumer = dispatch_queue_create("get_buffer", NULL);
dispatch_async(producer,
^{
int i;
do
{
put_buffer( buffer, in, out );
dispatch_async(consumer,
^{
get_buffer( buffer, in, out );
if (i == RUN_LENGTH) exit(EXIT_SUCCESS);
});
}
while (i < RUN_LENGTH);
});
dispatch_main();
deconstructer();
exit (0);
}
Your code has a bug. In the init function you assign the address of a local variable to semaphore->mutex1, and when the function returns this address will be invalid. Later you still use this address, so this leads to undefined behavior.
You must either allocate the memory for the mutex directly in the semaphore (without a pointer) or allocate the memory via malloc.
Update:
Your program has so many bugs that you should definitely pick an easier topic to learn the basic concepts about memory management, how to allocate, use and reference a buffer, do proper error handling, etc. Here is a slightly edited version of your code. It still won't work, but probably has some ideas that you should follow.
#include <limits.h>
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
void procure(Semaphore *semaphore) {
pthread_mutex_lock(semaphore->mutex1);
while (semaphore->value <= 0)
pthread_cond_wait(&semaphore->condition, semaphore->mutex1);
semaphore->value--;
pthread_mutex_unlock(semaphore->mutex1);
}
void vacate(Semaphore *semaphore) {
pthread_mutex_lock(semaphore->mutex1);
semaphore->value++;
pthread_cond_signal(&semaphore->condition);
pthread_mutex_unlock(semaphore->mutex1);
}
struct variables {
mutex_t sem_mutex;
Semaphore sem;
};
struct variables vars;
void constructor(int *buffer, int *in, int *out) {
vars.sem.value = 1;
vars.sem.mutex1 = &vars.sem_mutex;
pthread_mutex_init(vars.sem.mutex1, NULL);
}
void deconstructor() {
pthread_mutex_destroy(&semaphore->mutex1);
}
int rand_num_gen() {
const char *randomfile = "/dev/random";
unsigned char buffer[2]; // Changed: always treat files as byte sequences.
FILE *f = fopen(randomfile, "rb");
// Changed: using stdio instead of raw POSIX file access,
// since the API is much simpler; you don't have to care
// about interrupting signals or partial reads.
if (f == NULL) { // Added: error handling
fprintf(stderr, "E: cannot open %s\n", randomfile);
exit(EXIT_FAILURE);
}
if (fread(buffer, 1, 2, f) != 2) { // Added: error handling
fprintf(stderr, "E: cannot read from %s\n", randomfile);
exit(EXIT_FAILURE);
}
fclose(f);
int number = (buffer[0] << CHAR_BIT) | buffer[1];
// Changed: be independent of the endianness of the system.
// This doesn't matter for random number generators but is
// still an important coding style.
printf("DEBUG: random number: %x\n", (unsigned int) number);
return number;
}
void put_buffer( int* buffer, int* in, int* out ) {
buffer[*in] = rand_num_gen(); // produce
procure(&vars.sem); // wait here
*in = (*in + 1) % BUF_SIZE;
vacate(&vars.sem);
}
void get_buffer( int* buffer, int* in, int* out ) {
int value;
procure(&vars.sem);
value = buffer[*out];
vacate(&vars.sem);
*out = (*out + 1) % BUF_SIZE;
}
int main (void) {
int inindex = 0, outindex = 0;
int buffer[BUF_SIZE];
constructor(buffer, &inindex, &outindex);
// Changed: provided an actual buffer and actual variables
// for the indices into the buffer.
dispatch_queue_t producer, consumer;
producer = dispatch_queue_create("put_buffer", NULL);
consumer = dispatch_queue_create("get_buffer", NULL);
dispatch_async(producer, ^{
int i;
do {
put_buffer(buffer, &inindex, &outindex);
dispatch_async(consumer, ^{
get_buffer(buffer, &inindex, &outindex);
if (i == RUN_LENGTH) exit(EXIT_SUCCESS);
});
} while (i < RUN_LENGTH);
});
dispatch_main();
deconstructor();
exit (0);
}
As I said, I didn't catch all the bugs.