#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <semaphore.h>
#include <time.h>
int sleepval = 10, read_num = 0;
int readcnt = 0, writecnt = 0;
pthread_mutex_t mutex;
sem_t rw_mutex;
int randomGenerator(int high, int low){
srand(time(0));
return((rand() % (high - low + 1)) + 100);
}
void *reader(void *readno){
pthread_mutex_lock(&mutex);
read_num++;
/* Block the writer if this is the first reader */
if(read_num == 1){
sem_wait(&rw_mutex);
}
pthread_mutex_unlock(&mutex);
/* Read sleepval value and print */
printf("Reader %03d reads %d\n", *((int *)readno), sleepval);
readcnt++;
sleep(sleepval / 1000);
pthread_mutex_lock(&mutex);
read_num--;
/*Wake up writer if this is the last reader */
if(read_num == 0){
sem_post(&rw_mutex);
}
pthread_mutex_unlock(&mutex);
int num = randomGenerator(500, 100);
sleep(num / 1000);
}
void *writer(void *writeno){
int num = randomGenerator(1000, 100);
sleep(num / 1000);
num = randomGenerator(50, 10);
sem_wait(&rw_mutex);
sleepval = num;
printf("Writer %02d writes &d\n", *((int*)writeno), sleepval);
writecnt++;
sleep(sleepval / 1000);
sem_post(&rw_mutex);
}
int main(int argc, char *argv[]){
int r = atoi(argv[1]);
int w = atoi(argv[2]);
int second = 0;
int i, id[100];
if(r < 1 || r > 100 || w < 1 || w > 10){
fprintf(stderr, "Usage: readwrite [read](1 - 100) [write](1 - 10)\n");
exit(-1);
}
pthread_t read[100], write[10];
pthread_mutex_init(&mutex, NULL);
sem_init(&rw_mutex, 0 , 1);
/* Create threads for readers */
for(i = 0; i < r; i++){
id[i] = i;
pthread_create(&read[i], NULL, (void *)reader, (void *)&id[i]);
}
/* Create threads for writers */
for(i = 0; i < w; i++){
id[i] = i;
pthread_create(&write[i], NULL, (void *)writer, (void *)&id[i]);
}
sleep(30); //wait for 30 seconds
/* Signal threads to finish */
for (i = 0; i < r; i++){
pthread_join(read[i], NULL);
}
for (i = 0; i < w; i++){
pthread_join(write[i], NULL);
}
/* Display number of occurred reads and writes */
printf("\n==============================\n");
printf("Number of reads :\t%03d\n", readcnt);
printf("Number of writes :\t%03d\n", writecnt);
pthread_mutex_destroy(&mutex);
sem_destroy(&rw_mutex);
return 0;
}
This assignment is about solving the first reader-writer problem. I could compile it in linux using gcc -lpthread -lrt. But when I try to run it using the given format readwrtie 100 10 I got the segmentation fault (core dump) and I don't know why. I tried running with valgrind a.out to see the problem and I couldnt understand. Please help me.
Memcheck, a memory error detector
==19787== Copyright (C) 2002-2012, and GNU GPL'd, by Julian Seward et al.
==19787== Using Valgrind-3.8.1 and LibVEX; rerun with -h for copyright info
==19787== Command: a.out
==19787==
==19787== Invalid read of size 1
==19787== at 0x57E7AC: ____strtol_l_internal (in /lib/libc-2.12.so)
==19787== by 0x57E50F: strtol (in /lib/libc-2.12.so)
==19787== by 0x57AEB0: atoi (in /lib/libc-2.12.so)
==19787== by 0x8048A32: main (in /gaia/class/student/maih/maih-asgmt3/a.out)
==19787== Address 0x0 is not stack'd, malloc'd or (recently) free'd
==19787==
==19787==
==19787== Process terminating with default action of signal 11 (SIGSEGV)
==19787== Access not within mapped region at address 0x0
==19787== at 0x57E7AC: ____strtol_l_internal (in /lib/libc-2.12.so)
==19787== by 0x57E50F: strtol (in /lib/libc-2.12.so)
==19787== by 0x57AEB0: atoi (in /lib/libc-2.12.so)
==19787== by 0x8048A32: main (in /gaia/class/student/maih/maih-asgmt3/a.out)
==19787== If you believe this happened as a result of a stack
==19787== overflow in your program's main thread (unlikely but
==19787== possible), you can try to increase the size of the
==19787== main thread stack using the --main-stacksize= flag.
==19787== The main thread stack size used in this run was 10485760.
==19787==
==19787== HEAP SUMMARY:
==19787== in use at exit: 0 bytes in 0 blocks
==19787== total heap usage: 0 allocs, 0 frees, 0 bytes allocated
==19787==
==19787== All heap blocks were freed -- no leaks are possible
==19787==
==19787== For counts of detected and suppressed errors, rerun with: -v
==19787== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 13 from 8)
Segmentation fault (core dumped)
In your writer function, change
printf("Writer %02d writes &d\n", *((int*)writeno), sleepval);
---------------------------^
to
printf("Writer %02d writes %d\n", *((int*)writeno), sleepval);
---------------------------^
In your main function, change
pthread_create(&read[i], NULL, (void *)reader, (void *)&id[i]);
pthread_create(&write[i], NULL, (void *)writer, (void *)&id[i]);
to
pthread_create(&read[i], NULL, reader, &id[i]);
pthread_create(&write[i], NULL, writer, &id[i]);
Add a return statement to the reader and writer function.
Remove the unused variable second in the main function.
Try again.
Related
Context: Explanation of pointing to same address problem
compile:
gcc \
-Wpointer-arith -Wendif-labels \
-Wimplicit-fallthrough -Wmissing-format-attribute \
-Wcast-function-type -Wshadow=compatible-local \
-Wformat-security -Wno-format-truncation -Wno-stringop-truncation \
main.c &&./a.out dat/test.csv
Code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include<errno.h>
enum {MAXB = 128, NELEM = 10};
typedef struct data_t{
char *name;
int id;
double balance;
}data_t;
int main(int argc,char **argv)
{
if(argc < 2){
printf("No file input.foramt a.out filename. %s\n",argv[1]);
exit(EXIT_FAILURE);
}
FILE *fp = fopen(argv[1],"r");
if(fp == NULL){
printf("file not found\n");
exit(EXIT_FAILURE);
}
char buffer[MAXB] = "";
const char *delim = ",\n";
int index = 0;
data_t **array = malloc(NELEM * sizeof *array);
if(!array){ /* validate EVERY allocation */
perror("malloc-array failed\n");
exit(EXIT_FAILURE);
}
/* protect the allocation bounds, you only have NELEM pointers */
while (index < NELEM && fgets(buffer,sizeof buffer,fp))
{
data_t customer;
size_t len = 0;
char *tmp; /* temporary pointer to use w/strtok() */
tmp = strtok(buffer,delim); /* token for name */
if(!tmp) /* validate token */
{
fputs("error: strtok() name.\n",stderr);
exit(EXIT_FAILURE);
}
len = strlen(tmp); /* get length */
customer.name = malloc(len+1); /* allocate for string */
if(!customer.name)
{
perror("malloc-customer.name\n");
exit(EXIT_FAILURE);
}
memcpy(customer.name,tmp, len +1); /* copy tmp to .name */
if(!(tmp = strtok(NULL,delim))) /* token & validations */
{
fprintf(stderr,"error: strtok() -id.\n");
exit(EXIT_FAILURE);
}
/* MINIMAL conversion validation with sscanf() */
if(sscanf(tmp,"%d",&customer.id) != 1){
fprintf(stderr,"error: invalid integer value for line[%d]\n",index+1);
continue;
/* exit(EXIT_FAILURE); */
}
if(!(tmp = strtok(NULL,delim))){
fprintf(stderr,"\nerror: strtok()-balance shuld have more line\n");
continue;
// exit(EXIT_FAILURE);
}
if(sscanf(tmp,"%lf", &customer.balance) != 1){
fprintf(stderr,"error: invalid float value for line[%d]\n", index+1);
/* exit(EXIT_FAILURE); */
continue;
}
array[index] = malloc(sizeof *array[index]); /* allocate struct */
if(!array[index]){ /* validate!! */
perror("malloc-array[index]");
exit(EXIT_FAILURE);
}
*array[index] = customer; /* assign struct */
index += 1;
}
fclose(fp);
int i;
printf("\nname\tid\t balance\n\n");
for(i = 0; i< index; i++)
printf("%s \t%d\t%f\n",array[i]->name,array[i]->id,array[i]->balance);
for(i = 0; i< index; i++)
{
if(array[i]->name)
free(array[i]->name); /* free allocated block for name */
if(array[i])
free(array[i]); /* free allocated array index */
}
free(array);
exit(EXIT_FAILURE);
}
cat dat/test.csv returns
name,id,balance
test1,11,1.2334
test2,12,1.133
test3,13,1.3334
test4,14,1.4334
command valgrind -s --leak-check=full ./a.out dat/test.csv output:
==494197== Memcheck, a memory error detector
==494197== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==494197== Using Valgrind-3.18.1 and LibVEX; rerun with -h for copyright info
==494197== Command: ./a.out dat/test.csv
==494197==
error: invalid integer value for line[1]
name id balance
test1 11 1.233400
test2 12 1.133000
test3 13 1.333400
test4 14 1.433400
==494197== Memcheck, a memory error detector
==494197== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==494197== Using Valgrind-3.18.1 and LibVEX; rerun with -h for copyright info
==494197== Command: ./a.out dat/test.csv
==494197==
error: invalid integer value for line[1]
name id balance
test1 11 1.233400
test2 12 1.133000
test3 13 1.333400
test4 14 1.433400
==494197==
==494197== HEAP SUMMARY:
==494197== in use at exit: 5 bytes in 1 blocks
==494197== total heap usage: 13 allocs, 12 frees, 5,797 bytes allocated
==494197==
==494197== 5 bytes in 1 blocks are definitely lost in loss record 1 of 1
==494197== at 0x4848899: malloc (in /usr/libexec/valgrind/vgpreload_memcheck-amd64-linux.so)
==494197== by 0x10951D: main (in /home/jian/helloc/a.out)
==494197==
==494197== LEAK SUMMARY:
==494197== definitely lost: 5 bytes in 1 blocks
==494197== indirectly lost: 0 bytes in 0 blocks
==494197== possibly lost: 0 bytes in 0 blocks
==494197== still reachable: 0 bytes in 0 blocks
==494197== suppressed: 0 bytes in 0 blocks
==494197==
==494197== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)
After a compilation with no warnings and errors for my file reorg.c, I am running the program using Valgrind and I am getting the following output. I am trying to understand why I am getting a segmentation fault but I can't really find something wrong with line 35:
Memcheck, a memory error detector
==29338== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==29338== Using Valgrind-3.18.1 and LibVEX; rerun with -h for copyright info
==29338== Command: ./reorg /opt/lsde/dataset-sf100/
==29338==
==29338== Invalid read of size 2
==29338== at 0x109398: main (reorg.c:35)
==29338== Address 0x12cb4008 is not stack'd, malloc'd or (recently) free'd
==29338==
==29338==
==29338== Process terminating with default action of signal 11 (SIGSEGV)
==29338== Access not within mapped region at address 0x12CB4008
==29338== at 0x109398: main (reorg.c:35)
==29338== If you believe this happened as a result of a stack
==29338== overflow in your program's main thread (unlikely but
==29338== possible), you can try to increase the size of the
==29338== main thread stack using the --main-stacksize= flag.
==29338== The main thread stack size used in this run was 8388608.
==29338==
==29338== HEAP SUMMARY:
==29338== in use at exit: 15,280 bytes in 10 blocks
==29338== total heap usage: 10 allocs, 0 frees, 15,280 bytes allocated
==29338==
==29338== LEAK SUMMARY:
==29338== definitely lost: 5,120 bytes in 5 blocks
==29338== indirectly lost: 0 bytes in 0 blocks
==29338== possibly lost: 0 bytes in 0 blocks
==29338== still reachable: 10,160 bytes in 5 blocks
==29338== suppressed: 0 bytes in 0 blocks
==29338== Rerun with --leak-check=full to see details of leaked memory
==29338==
==29338== For lists of detected and suppressed errors, rerun with: -s
==29338== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)
Segmentation fault (core dumped)
This is the code of the reorg.c program.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include "utils.h"
Person *person_map;
unsigned int *knows_map;
unsigned short *interest_map;
unsigned long person_num = 0;
int main(int argc, char *argv[]) {
unsigned long file_length;
interest_map = (unsigned short *) mmapr(makepath(argv[1], "interest", "bin"), &file_length);
printf("amin1");
knows_map = (unsigned int *) mmapr(makepath(argv[1], "knows", "bin"), &file_length);
printf("amin2");
person_map = (Person *) mmapr(makepath(argv[1], "person", "bin"), &file_length);
printf("amin3");
knows_map = (unsigned int *) mmapr(makepath(argv[1], "knows", "bin"), &file_length);
printf("knows");
person_map = (Person *) mmapr(makepath(argv[1], "person", "bin"), &file_length);
printf("person");
person_num = file_length/sizeof(person_map);
int counter=0;
FILE* fp_knows2 = fopen(makepath(argv[1], "knows2", "bin"), (char*) "w");
FILE* fp_person2 = fopen(makepath(argv[1], "person2", "bin"), (char*) "w");
long knows2_bytesize;
int *knows2_map;
int *person2_map;
long person2_bytesize;
for(long i=0; i<person_num; i++) {
for(long j = 0; j < person_map[i].knows_n; j++) {
int friend = knows_map[person_map[i].knows_first+j]; // person in my knows-list
if (person_map[friend].location == person_map[i].location) {
counter++;
fwrite(&friend, 1,sizeof(int), fp_knows2);
}
}
if(counter > 0){
fwrite(&person_map[i], 1, sizeof(int), fp_person2);
}
counter=0;
}
fclose(fp_knows2);
fclose(fp_person2);
person2_map = (int*) mmapr(makepath(argv[1], "person2","bin"), &person2_bytesize);
knows2_map = (int*) mmapr(makepath(argv[1], "knows2","bin"), &knows2_bytesize);
return 0;
}
And this is the code of the utils.h program that am including in:
#define REPORTING_N 1000000
#define LINEBUFLEN 1024
typedef unsigned long byteoffset;
typedef unsigned int entrycount;
typedef struct {
unsigned long person_id;
unsigned short birthday;
unsigned short location;
unsigned long knows_first;
unsigned short knows_n;
unsigned long interests_first;
unsigned short interest_n;
} Person;
void parse_csv(char* fname, void (*line_handler)(unsigned char nfields, char** fieldvals)) {
long nlines = 0;
FILE* stream = fopen(fname, "r");
if (stream == NULL) {
fprintf(stderr, "Can't read file at %s\n", fname);
exit(-1);
}
char line[LINEBUFLEN];
char* tokens[10];
unsigned int col, idx;
tokens[0] = line;
while (fgets(line, LINEBUFLEN, stream)) {
col = 0;
// parse the csv line into array of strings
for (idx=0; idx<LINEBUFLEN; idx++) {
if (line[idx] == '|' || line[idx] == '\n') {
line[idx] = '\0';
col++;
tokens[col] = &line[idx+1];
} // lookahead to find end of line
if (line[idx+1] == '\0') {
break;
}
}
(*line_handler)(col, tokens);
nlines++;
if (nlines % REPORTING_N == 0) {
printf("%s: read %lu lines\n", fname, nlines);
}
}
fclose(stream);
}
FILE* open_binout(char* filename) {
FILE* outfile;
outfile = fopen(filename, "wb");
if (outfile == NULL) {
fprintf(stderr, "Could not open %s for writing\n", filename);
exit(-1);
}
return outfile;
}
unsigned short birthday_to_short(char* date) {
unsigned short bdaysht;
char dmbuf[3];
dmbuf[2] = '\0';
dmbuf[0] = *(date + 5);
dmbuf[1] = *(date + 6);
bdaysht = atoi(dmbuf) * 100;
dmbuf[0] = *(date + 8);
dmbuf[1] = *(date + 9);
bdaysht += atoi(dmbuf);
return bdaysht;
}
void* mmapr(char* filename, byteoffset *filelen) {
int fd;
struct stat sbuf;
void *mapaddr;
if ((fd = open(filename, O_RDONLY)) == -1) {
fprintf(stderr, "failed to open %s\n", filename);
exit(1);
}
if (stat(filename, &sbuf) == -1) {
fprintf(stderr, "failed to stat %s\n", filename);
exit(1);
}
mapaddr = mmap(0, sbuf.st_size, PROT_READ, MAP_SHARED, fd, 0);
if (mapaddr == MAP_FAILED) {
fprintf(stderr, "failed to mmap %s\n", filename);
exit(1);
}
*filelen = sbuf.st_size;
return mapaddr;
}
char* makepath(char* dir, const char* file, const char* ext) {
char* out = (char*) malloc(1024), *sep = (char*) "";
if (strlen(dir) && dir[strlen(dir)-1] != '/') sep = (char*) "/";
sprintf(out, "%s%s%s.%s", dir, sep, file, ext);
return out;
}
I'm working on the sleeping barber problem (using FIFO queue and shared memory), and I have a problem. I try to run this program just to see what is shown, however, I get segmentation fault every time. In the code I check, if semaphores are created successfully, if shared memory is created properly, but the program crashing must come from different place, which I cannot seem to find. I also tried to use Valgrind but what I got is:
Valgrind for the newer version of code:
However, when I try to run the code I still get segfault
==187== Memcheck, a memory error detector
==187== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==187== Using Valgrind-3.15.0 and LibVEX; rerun with -h for copyright info
==187== Command: ./barber
==187==
Error while executing program, invalid amount of arguments==187==
==187== HEAP SUMMARY:
==187== in use at exit: 0 bytes in 0 blocks
==187== total heap usage: 1 allocs, 1 frees, 1,024 bytes allocated
==187==
==187== All heap blocks were freed -- no leaks are possible
==187==
==187== For lists of detected and suppressed errors, rerun with: -s
==187== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
==124== Memcheck, a memory error detector
==124== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==124== Using Valgrind-3.15.0 and LibVEX; rerun with -h for copyright info
==124== Command: ./barber
==124==
==124== Invalid read of size 1
==124== at 0x1094DD: main (in /mnt/c/users/Czaro/ubuntu/lab6posix/barber)
==124== Address 0x2 is not stack'd, malloc'd or (recently) free'd
==124==
==124==
==124== Process terminating with default action of signal 11 (SIGSEGV)
==124== Access not within mapped region at address 0x2
==124== at 0x1094DD: main (in /mnt/c/users/Czaro/ubuntu/lab6posix/barber)
==124== If you believe this happened as a result of a stack
==124== overflow in your program's main thread (unlikely but
==124== possible), you can try to increase the size of the
==124== main thread stack using the --main-stacksize= flag.
==124== The main thread stack size used in this run was 8388608.
glut==124==
==124== HEAP SUMMARY:
==124== in use at exit: 125 bytes in 4 blocks
==124== total heap usage: 5 allocs, 1 frees, 1,149 bytes allocated
==124==
==124== LEAK SUMMARY:
==124== definitely lost: 0 bytes in 0 blocks
==124== indirectly lost: 0 bytes in 0 blocks
==124== possibly lost: 0 bytes in 0 blocks
==124== still reachable: 125 bytes in 4 blocks
==124== suppressed: 0 bytes in 0 blocks
==124== Reachable blocks (those to which a pointer was found) are not shown.
==124== To see them, rerun with: --leak-check=full --show-leak-kinds=all
==124==
==124== For lists of detected and suppressed errors, rerun with: -s
==124== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)
Segmentation fault
I'd greatly appreciate every kind of help!
The code for barber (newer version, with changes given by #AndrewHenle looks like this:
#include <stdio.h>
#include <stdlib.h>
#include <semaphore.h>
#include <sys/stat.h>
#include <fcntl.h>
#include "functions.h"
#include <sys/mman.h>
#include <unistd.h>
int main(char* argv[], int argc)
{
if(argc < 2){
printf("Error while executing program, invalid amount of arguments");
return 0;
}
sem_t *barber;
sem_t *queue;
int seats;
int sharedmem, waitRoomSize;
struct Queue waitroom;
barber = sem_open("Barber", O_CREAT | O_RDWR, 0666, 1);
if((barber == SEM_FAILED)){
printf("Error while creating semaphore for barber");
exit(1);
}
queue = sem_open("Queue", O_CREAT | O_RDWR, 0666, 1);
if((queue == SEM_FAILED)) {
printf("Error while creating semaphore for queue");
exit(1);
}
seats = atoi(argv[1]);
void *space;
queueinit(waitroom, seats);
sharedmem = shm_open("Queue", O_RDWR, 0666);
if(sharedmem==-1){
printf("Error while getting shared memory");
exit(1);
}
waitRoomSize = ftruncate(sharedmem, sizeof(waitroom));
if((waitRoomSize ==-1)){
printf("Error while getting size");
exit(1);
}
space = mmap(NULL, sizeof(struct Queue), PROT_READ | PROT_WRITE, MAP_SHARED, sharedmem, 0);
if((space == MAP_FAILED)){
printf("B³¹d podczas mapowania pamiêci");
exit(1);
}
while(1)
{
printf("Starting work...");
sem_wait(queue);
sem_post(queue);
if(isEmpty(waitroom)) {
sem_wait(barber);
printf("Falling asleep \n");
sem_post(barber);
printf("Waking up \n");
}
sem_wait(queue);
sem_post(queue);
int id = get(waitroom);
printf("Customer: %d, please sit on the chair", id);
printf("I start making haircut: %d", id);
sleep(2);
printf("Finished making haircut for: %d", id);
}
sem_close(barber);
sem_unlink("Barber");
sem_close(queue);
sem_unlink("Queue");
}
Previous version:
#include <stdio.h>
#include <stdlib.h>
#include <semaphore.h>
#include <sys/stat.h>
#include <fcntl.h>
#include "functions.h"
#include <sys/mman.h>
#include <unistd.h>
int main(char* argv, int argc)
{
sem_t *barber;
sem_t *queue;
int seats;
int sharedmem, waitRoomSize;
struct Queue waitroom;
barber = sem_open("Barber", O_CREAT | O_RDWR, 0666, 1);
if((barber == SEM_FAILED)){
printf("Error while creating semaphore for barber");
exit(1);
}
queue = sem_open("Queue", O_CREAT | O_RDWR, 0666, 1);
if((queue == SEM_FAILED)) {
printf("Error while creating semaphore for queue");
exit(1);
}
seats = atoi(argv[1]);
void *space;
queueinit(waitroom, seats);
if((sharedmem = shm_open("Queue", O_RDWR, 0666)==-1)){
printf("Error while getting shared memory");
exit(1);
}
if((waitRoomSize = ftruncate(sharedmem, sizeof(waitroom))==-1)){
printf("Error while getting size");
exit(1);
}
if((space = mmap(NULL, sizeof(struct Queue), PROT_READ | PROT_WRITE, MAP_SHARED, sharedmem, 0) == MAP_FAILED)){
printf("Błąd podczas mapowania pamięci");
exit(1);
}
while(1)
{
printf("Starting work...");
sem_wait(queue);
sem_post(queue);
if(isEmpty(waitroom)) {
sem_wait(barber);
printf("Falling asleep \n");
sem_post(barber);
printf("Waking up \n");
}
sem_wait(queue);
sem_post(queue);
int id = get(waitroom);
printf("Customer: %d, please sit on the chair", id);
printf("I start making haircut: %d", id);
sleep(2);
printf("Finished making haircut for: %d", id);
}
sem_close(barber);
sem_unlink("Barber");
sem_close(queue);
sem_unlink("Queue");
}
The FIFO queue is implemented like this:
#ifndef FUNCTIONS_H_INCLUDED
#define FUNCTIONS_H_INCLUDED
#include <stdlib.h>
#include <unistd.h>
struct Queue{
int* elems;
int qsize;
int head;
int tail;
int capacity;
};
void queueinit(struct Queue q, int capacity)
{
q.elems = malloc(capacity*(sizeof(int)));
q.capacity = capacity;
q.head = 0;
q.qsize = 0;
q.tail = capacity-1;
}
int isFull(struct Queue q)
{
return (q.qsize == q.capacity);
}
int isEmpty(struct Queue q)
{
return (q.qsize == 0);
}
void push(struct Queue q, int val)
{
if(isFull(q)){
printf("Kolejka pe³na");
return;
}
q.tail = (q.tail +1) % q.capacity;
q.elems[q.tail] = val;
q.qsize = q.qsize +1;
printf("%d zajmuje miejsce w kolejce", val);
}
int get(struct Queue q)
{
if(isEmpty(q))
{
printf("kolejka pusta");
return -1;
}
int val = q.elems[q.head];
q.head = (q.head +1) % q.capacity;
q.qsize = q.qsize -1;
printf("%d opuszcza zak³ad", val);
}
#endif // FUNCTIONS_H_INCLUDED
Im writing a library of functions that works with shared memory. The function I am writing to close the shared memory gives me a segfault whenever it gets to the munmap() part, but if i dont use the function and just let the code munmap() and shm_unlink at the end, it works. im very confused as to why. the code is below.
void close_table(table_t *tbl, char* name){
size_t size = sizeof(tbl->table_size);
printf("table_size: %d\n", tbl->table_size);
/* when the first part of if else statement runs its fine */
if(tbl->numP > 1){
printf("first if statement\n");
tbl->numP -= 1;
munmap(tbl, tbl->table_size);
}
/* when second part runs gives seg fault */
else{
tbl->numP -= 1;
munmap(tbl, tbl->table_size);
//close(tbl->shm_fd);
shm_unlink(tbl->name);
}
// Code omission
}
This is the open table function
table_t *open_table(char *name, int record_size, int max_records){
int shm_fd;
int table_size;
void* ptr;
table_t* tbl;
table_t controlBlock;
db_info info;
data_block data;
table_size = max_records * sizeof(controlBlock) * sizeof(info) *
sizeof(data);
if((shm_fd = shm_open(name, O_CREAT | O_RDWR, 0666)) == -1){
exit(EXIT_FAILURE);
}
ftruncate(shm_fd, table_size);
ptr = mmap(NULL, table_size, PROT_WRITE | PROT_READ, MAP_SHARED, shm_fd,
0);
tbl = ptr;
tbl->shm_fd = shm_fd;
tbl->table_size = table_size;
tbl->max_records = max_records;
tbl->record_size = record_size;
if(tbl->numP >= 1){
tbl->numP += 1;
}
else{
tbl->numP = 1;
}
return tbl;
}
these are my structs
typedef struct{
int dbInfoId;
int deleted;
}db_info;
typedef struct{
int shm_fd;
int numP;
int control_id;
char *name;
int table_size;
int record_size;
int max_records;
db_info* dbInfo;
void* db;
}table_t;
typedef struct{
int id;
void* record;
}data_block;
valgrind says its an "invalid read of size 8
enter a command (just the number):
1. Add
2. Delete
3. Process
4. Close
5. # of processes
6. exit
4
table_size: 29360128
==6679== Invalid read of size 8
==6679== at 0x108C42: close_table (in /home/abiodun/Documents/Comp 3713/Assignment3_makeup/main)
==6679== by 0x108F15: main (main.c:40)
==6679== Address 0x5654010 is not stack'd, malloc'd or (recently) free'd
==6679==
==6679==
==6679== Process terminating with default action of signal 11 (SIGSEGV)
==6679== Access not within mapped region at address 0x5654010
==6679== at 0x108C42: close_table (in /home/abiodun/Documents/Comp 3713/Assignment3_makeup/main)
==6679== by 0x108F15: main (main.c:40)
==6679== If you believe this happened as a result of a stack
==6679== overflow in your program's main thread (unlikely but
==6679== possible), you can try to increase the size of the
==6679== main thread stack using the --main-stacksize= flag.
==6679== The main thread stack size used in this run was 8388608.
--6679-- REDIR: 0x50db950 (libc.so.6:free) redirected to 0x4c30cd0 (free)
==6679==
==6679== HEAP SUMMARY:
==6679== in use at exit: 0 bytes in 0 blocks
==6679== total heap usage: 2 allocs, 2 frees, 2,048 bytes allocated
==6679==
==6679== All heap blocks were freed -- no leaks are possible
==6679==
==6679== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)
==6679==
==6679== 1 errors in context 1 of 1:
==6679== Invalid read of size 8
==6679== at 0x108C42: close_table (in /home/abiodun/Documents/Comp 3713/Assignment3_makeup/main)
==6679== by 0x108F15: main (main.c:40)
==6679== Address 0x5654010 is not stack'd, malloc'd or (recently) free'd
==6679==
==6679== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)
Segmentation fault (core dumped)
I figured it the answer. It turns out I was still trying to access variables in the tbl struct after it was unmapped. so to fix this I just created variabbles in the function and saved what I needed from the tbl struct before unmapping.
void close_table(table_t *tbl){
int size = tbl->table_size;
char* name = tbl->name;
int fd = tbl->shm_fd;
printf("table_size: %d\n", tbl->table_size);
if(tbl->numP > 1){
tbl->numP -= 1;
munmap(tbl, tbl->table_size);
close(fd);
}
else if(tbl->numP == 1){
tbl->numP -= 1;
munmap(tbl, size);
printf("unmap works\n"); fflush(stdout);
shm_unlink(name);
close(fd);
}
I have the following code:
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include <stdlib.h>
#include <sys/stat.h>
void print_usage()
{
printf("%s\n", "usage");
}
int file_exist (char *filename)
{
struct stat buffer;
return (stat (filename, &buffer) == 0);
}
int parse_parameters(int argc, char *argv[], char** in)
{
unsigned int i1 = 1; // 0 is the filename
for (; i1 < argc; ++i1)
{
if( 0 == strcmp("-h", argv[i1]) )
{
print_usage();
return 0;
}
else if( 0 == strcmp("-i", argv[i1]) )
{
*in = malloc( sizeof(char) * strlen(argv[++i1]) + 1 );
strcpy(*in, argv[i1]);
continue;
}
else
{
print_usage();
return 1;
}
}
return 0;
}
int main(int argc, char *argv[])
{
if( argc != 3 )
{
print_usage();
return 0;
}
char* in = NULL;
int parse = parse_parameters(argc, argv, &in);
if ( 0 != parse )
return parse;
printf("in: %s\n", in);
FILE* finput = NULL ;
if (file_exist(in))
finput = fopen(in, "r");
if (finput == NULL) {
perror("fopen");
exit(1);
}
free(in);
fclose(finput);
return 0;
}
After running it with valgrind with following parameters:
./main -i input
I get the following:
==30977== Memcheck, a memory error detector
==30977== Copyright (C) 2002-2013, and GNU GPL'd, by Julian Seward et al.
==30977== Using Valgrind-3.10.0.SVN and LibVEX; rerun with -h for copyright info
==30977== Command: ./main -i input
==30977==
in: input
fopen: No such file or directory
==30977==
==30977== HEAP SUMMARY:
==30977== in use at exit: 6 bytes in 1 blocks
==30977== total heap usage: 2 allocs, 1 frees, 574 bytes allocated
==30977==
==30977== 6 bytes in 1 blocks are still reachable in loss record 1 of 1
==30977== at 0x4C2AB80: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==30977== by 0x400946: parse_parameters (main.c:31)
==30977== by 0x4009E7: main (main.c:54)
==30977==
==30977== LEAK SUMMARY:
==30977== definitely lost: 0 bytes in 0 blocks
==30977== indirectly lost: 0 bytes in 0 blocks
==30977== possibly lost: 0 bytes in 0 blocks
==30977== still reachable: 6 bytes in 1 blocks
==30977== suppressed: 0 bytes in 0 blocks
==30977==
==30977== For counts of detected and suppressed errors, rerun with: -v
==30977== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
Why is that ? If I try to pass in as char* then it won't get changed after the parse_parameters function.
Your program is exiting as a result of the exit (1) call, which occurs before you free (in). As a result you are seeing the valgrind message.