Segmentation fault podczas uzywania statycznej biblioteki

0

Mam problem z moim plikiem hash.c w ktorym mam implementacje hashlisty i plik main.c ktory wykorzystuje funkcje z hash.c. Main.c dostarcza dla hash.c dwie funkcje tj. funkcje hashującą i wypisującą elementy aby kod w hash.c byl nieco uniwersalny i mogl przyjmowac rozne typy.

proboje stworzyc biblioteke i odpalic w taki sposob:

#!/bin/bash
gcc -c hash.c -o hash.o
ar r lib_hash.a hash.o
ar tv lib_hash.a
gcc -c main.c -o main.o
gcc main.o lib_hash.a -o result.out
./result.out // <- dostaje Segmentation fault(core dump)

main:

#include <stdio.h>
typedef int my_int;

void printInt(void *e) {
    my_int *tmp;
    tmp = (my_int *) e;
    printf("%d ", *tmp);
}

int generateHashInt(void *value) {
    my_int *tmp;
    tmp = (my_int *) value;
    return (*tmp) % 2;
}

int main() {
    struct hash_table *table = prepareHashTable(generateHashInt, printInt);

    int a = 10;
    int b = 11;
    int c = 12;

    add(table, (void *) &a);            //  <------------------- w tym miejscu zaczyna wywalac segmentation fault
    add(table, (void *) &b);
    add(table, (void *) &c);
    printValue(table, (void *) &a);

    deleteAll(table);
    return 0;
}

kawalek kodu z funkcją 'add':

void add(struct hash_table *hashTable, void *value) {
    int hashValue = hashTable->hashFun(value);
    if (hashTable->first == NULL) {
        hashTable->first = (struct hash_elem *) malloc(sizeof(struct hash_elem));
        hashTable->first->key = hashValue;
        hashTable->first->values = (struct list_struct *) malloc(sizeof(struct list_struct));
        hashTable->first->values->value = value;

        return;
    }

...reszta kodu do ktorego nie wchodzi

tutaj caly kod, wraz z mainem w jednym pliku i o dziwo w takim rozwiazaniu kod działa
https://ideone.com/bYVgaA

nie moge tego rozgryzc dlaczego to nie dziala gdy chce wykorzystac hash.c w innym pliku :(
debuggowalem funkcje add i z tego co widze, to wszystko sie dobrze alokuje

pomocy!

1

Jeśli alokujesz pamięć za pomocą malloca to zaalokowana przestrzeń zawiera w sobie losowe bajty.
Potrzebujesz wszystkie wskaźniki, które po zaalokowaniu na nic nie wskazują, ustawić na wartość NULL.

Korzystaj z narzędzi które pokazują Ci wycieki pamięci jak np Valgrind.
Nie wiem czy to wszystko co powinno być poprawione, czy przypadkiem nie jest czegoś za dużo, musisz to sprawdzić sam:

    struct hash_table *prepareHashTable(int(*hashFun)(void *), void(*printFun)(void *)) {
        struct hash_table *table = (struct hash_table *) malloc(sizeof(struct hash_table));
        table->printFun = printFun;
        table->hashFun = hashFun;
	table->first = NULL;			//#
        return table;
    }
     
    void add(struct hash_table *hashTable, void *value) {
        int hashValue = hashTable->hashFun(value);
        if (hashTable->first == NULL) {
            hashTable->first = (struct hash_elem *) malloc(sizeof(struct hash_elem));
	    hashTable->first->next = NULL;	//#
            hashTable->first->key = hashValue;
            hashTable->first->values = (struct list_struct *) malloc(sizeof(struct list_struct));
            hashTable->first->values->value = value;
	    hashTable->first->values->next = NULL;	//#
     
            return;
        }
     
        struct hash_elem *hashElem = hashTable->first;
        while (hashElem->key != hashValue) {
            if (hashElem->next != NULL)
                hashElem = hashElem->next;
            else {
                hashElem->next = (struct hash_elem *) malloc(sizeof(struct hash_elem));
		hashElem->next->values = NULL;	//#
		hashElem->next->next = NULL;	//#
                hashElem->next->key = hashValue;
                hashElem = hashElem->next;
            }
        }
     
        if (hashElem->values == NULL) {
            hashElem->values = (struct list_struct *) malloc(sizeof(struct list_struct));
	    hashElem->next = NULL;		//#
	    hashElem->values->next = NULL;	//#
            hashElem->values->value = value;
            return;
        }
     
        struct list_struct *listElem = hashElem->values;
     
        while (listElem->next != NULL) {
            listElem = listElem->next;
        }
        listElem->next = (struct list_struct *) malloc(sizeof(struct list_struct));
	listElem->next->next = NULL;		//#
        listElem->next->value = value;
     
    }

Linijki dodane oznaczyłem znakiem komentarza.
Dodatkowo czyszczenie pamięci nie jest wykonane w odpowiedni sposób.

0

A prepareHashTable też dobrze alokuje?

0

Spróbuj w prepapreHashTable ustawić table->first na NULL.

1

Nie odpowiadaj w komentarzach.
Co się stanie jak zlinkujesz (ostatni krok) hash.o zamiast lib_hash.a? Też się wysypie?

0

kurcze. niestety nadal segmentation fault

0

Ok. to teraz podepnij się do do dumpa debugerem i powiedz co pokazuje backtrace.

0
alagner napisał(a):

Ok. to teraz podepnij się do do dumpa debugerem i powiedz co pokazuje backtrace.

niestety nie za bardzo wiem jak to zrobić.

uzywajac jakiegos kawalka kodu z SO dostaje cos z czego za wiele chyba nie wynika:

Obtained 5 stack frames.
./result.out(+0x852) [0x55729bbec852]
./result.out(+0x8eb) [0x55729bbec8eb]
./result.out(+0x99a) [0x55729bbec99a]
/lib/x86_64-linux-gnu/libc.so.6(__libc_start_main+0xf1) [0x7f35caa181c1]
./result.out(+0x74a) [0x55729bbec74a]
Segmentation fault (core dumped)

1

A dodaj do wszystkich wywołań gcc -g3 -O0.
Potem ulimit -c unlimited przed uruchomieniem.
Odpalasz program, on idzie w maliny, na końcu robisz: gdb nazwa_program plik_z_dumpem (ten ostatni to typowo nr_pid.core, np 12345.core albo core.12345, powinien być w tym samym katalogu. Co to za system i jakie gcc tak btw?)

Potem w gdb thread apply all backtrace i wklejasz ;)

0

ale ze mnia łamaga, meczylem sie, zeby z powodzeniem wykonac wskazanie instrukcje :D
uzywam ubuntu 17, gcc 7.2.0

warning: core file may not match specified executable file.
[New LWP 7418]
Core was generated by `./result.out'.
Program terminated with signal SIGSEGV, Segmentation fault.
#0  0x0000558cdcd4c89e in add (hashTable=0xffffffffdec39260, value=0x7ffdf2f0d9f8) at hash.c:33
33	    int hashValue = hashTable->hashFun(value);
(gdb) thread apply all backtrace

Thread 1 (LWP 7418):
#0  0x0000558cdcd4c89e in add (hashTable=0xffffffffdec39260, value=0x7ffdf2f0d9f8) at hash.c:33
#1  0x0000558cdcd4c7f7 in main () at main.c:27
(gdb) 

czyzby moja funkcja

int generateHashInt(void *value) {
    my_int *tmp;
    tmp = (my_int *) value;
    return (*tmp) % 2;
}

byla tutaj zle przekazywana?:

table = prepareHashTable(generateHashInt, printInt);

#edit

jak podmienilem w kodzie a dokladnie w funkcji add, zeby zawsze hashValue=2
to dostaje nadal blad i takie efekt:

Core was generated by `./result.out'.
Program terminated with signal SIGSEGV, Segmentation fault.
#0  0x0000558cdcd4c89e in ?? ()
(gdb) thread apply all backtrace

Thread 1 (LWP 7418):
#0  0x0000558cdcd4c89e in ?? ()
#1  0x00007ffdf2f0d9f8 in ?? ()
#2  0xffffffffdec39260 in ?? ()
#3  0x0000558cdcd4c630 in ?? ()
#4  0x0000558cdcd4c85c in ?? ()
#5  0x0000558cdcd4c73a in ?? ()
#6  0x0000558cdcd4c76a in ?? ()
#7  0x0000000000000001 in ?? ()
#8  0x0000000000000000 in ?? ()
0

Na to wygląda. Masz tego dżenerejta w nagłówku?
EDIT: przeleć to przez nm i sprawdź adresy funkcji bo wygląda, że coś tam jest skopane...

0

dramat...
po dodaniu do nagłówka, problem pozostaje

chyba zaraz przepisze ten kod od nowa

0

A co pokazuje nm jak przelecisz nim po plikach .o, .a oraz wynikowej binarce?

0

main.o

                 U add
                 U _GLOBAL_OFFSET_TABLE_
0000000000000030 T hashFun
000000000000003f T main
                 U prepareHashTable
                 U printf
0000000000000000 T printInt
                 U printValue
                 U __stack_chk_fail
0000000000000000 n wm4.0.66d6a747e2c960a527cf92f27e079b15
0000000000000000 n wm4.cdefs.h.19.adeb16a64344c6d3415f3e54d476fcd5
0000000000000000 n wm4.cdefs.h.442.3a381d8c28278959570b8bd7b691535a
0000000000000000 n wm4.features.h.19.37a7a44d0de297f1956390dcad9f06e1
0000000000000000 n wm4._G_config.h.47.a82480968582d192e152a266f32f4832
0000000000000000 n wm4._G_config.h.5.b0f37d9e474454cf6e459063458db32f
0000000000000000 n wm4.libcheaderstart.h.37.59f0e5f6a6103fb6c1d4abef1aacf8fb
0000000000000000 n wm4.libio.h.33.a775b9ecae273f33bc59931e9891e4ca
0000000000000000 n wm4.libio.h.51.bfc1fde3b8eeb402147122161f2faa3c
0000000000000000 n wm4.stdarg.h.34.3a23a216c0c293b3d2ea2e89281481e6
0000000000000000 n wm4.stdcpredef.h.19.006d14bbbe0dc07ba9b1ce3fdc8e40d3
0000000000000000 n wm4.stddef.h.187.2ff233552538c6ff9b8575ca8ea52cb3
0000000000000000 n wm4.stddef.h.238.04cc7214bceba497b20d15c10fd97511
0000000000000000 n wm4.stdio.h.139.81d529aa6b2372d0b323a208652caa26
0000000000000000 n wm4.stdio.h.24.5c1b97eef3c86b7a2549420f69f4f128
0000000000000000 n wm4.stdio.h.31.e39a94e203ad4e1d978c0fc68ce016ee
0000000000000000 n wm4.stdio.h.47.29bae166896130ef16bc0206bf46f074
0000000000000000 n wm4.stdio_lim.h.19.e4b00b560d878dcfbc6635b3406640c5
0000000000000000 n wm4.stubs64.h.10.918ceb5fa58268542bf143e4c1efbcf3
0000000000000000 n wm4.types.h.98.2414c985b07b6bc05c8aeed70b12c683
0000000000000000 n wm4.typesizes.h.24.292526668b3d7d0c797f011b553fed17
0000000000000000 n wm4.wordsize.h.4.baf119258a1e53d8dba67ceac44ab6bc


hash.o

0000000000000047 T add
0000000000000212 T deleteAll
                 U free
                 U _GLOBAL_OFFSET_TABLE_
                 U malloc
0000000000000000 T prepareHashTable
00000000000002a3 T printValue
0000000000000000 n wm4.0.66d6a747e2c960a527cf92f27e079b15
0000000000000000 n wm4.alloca.h.19.edefa922a76c1cbaaf1e416903ba2d1c
0000000000000000 n wm4.alloca.h.29.156e12058824cc23d961c4d3b13031f6
0000000000000000 n wm4.byteswap.h.38.11ee5fdc0f6cc53a16c505b9233cecef
0000000000000000 n wm4.cdefs.h.19.adeb16a64344c6d3415f3e54d476fcd5
0000000000000000 n wm4.cdefs.h.442.3a381d8c28278959570b8bd7b691535a
0000000000000000 n wm4.endian.h.19.ff00c9c0f5e9f9a9719c5de76ace57b4
0000000000000000 n wm4.endian.h.41.24cced64aef71195a51d4daa8e4f4a95
0000000000000000 n wm4.endian.h.64.2d674ba9109a6d52d2a5fe14c9acf78f
0000000000000000 n wm4.features.h.19.37a7a44d0de297f1956390dcad9f06e1
0000000000000000 n wm4.floatn.h.20.8a8e31f41b94a2f8d9ecd5d457e564ca
0000000000000000 n wm4._G_config.h.47.a82480968582d192e152a266f32f4832
0000000000000000 n wm4._G_config.h.5.b0f37d9e474454cf6e459063458db32f
0000000000000000 n wm4.libcheaderstart.h.31.80e4950905f3c07b663af4c98f48a7c0
0000000000000000 n wm4.libcheaderstart.h.37.59f0e5f6a6103fb6c1d4abef1aacf8fb
0000000000000000 n wm4.libio.h.33.a775b9ecae273f33bc59931e9891e4ca
0000000000000000 n wm4.libio.h.51.bfc1fde3b8eeb402147122161f2faa3c
0000000000000000 n wm4.pthreadtypesarch.h.25.f0b4b4dcf6317b863c87da6854b5210f
0000000000000000 n wm4.select.h.28.eb2f3debdbcffd1442ebddaebc4fb6ff
0000000000000000 n wm4.select.h.44.887a4ff60aa97fcd9c1be017735e1675
0000000000000000 n wm4.__sigset_t.h.2.6b1ab6ff3d7b8fd9c0c42b0d80afbd80
0000000000000000 n wm4.stdarg.h.34.3a23a216c0c293b3d2ea2e89281481e6
0000000000000000 n wm4.stdcpredef.h.19.006d14bbbe0dc07ba9b1ce3fdc8e40d3
0000000000000000 n wm4.stddef.h.187.2ff233552538c6ff9b8575ca8ea52cb3
0000000000000000 n wm4.stddef.h.238.04cc7214bceba497b20d15c10fd97511
0000000000000000 n wm4.stddef.h.238.5c3398669aab31a6fd426ff45ca6ab2c
0000000000000000 n wm4.stddef.h.238.847b6907dabda77be90a9ab7ad789e2e
0000000000000000 n wm4.stdio.h.139.81d529aa6b2372d0b323a208652caa26
0000000000000000 n wm4.stdio.h.24.5c1b97eef3c86b7a2549420f69f4f128
0000000000000000 n wm4.stdio.h.31.e39a94e203ad4e1d978c0fc68ce016ee
0000000000000000 n wm4.stdio.h.47.29bae166896130ef16bc0206bf46f074
0000000000000000 n wm4.stdio_lim.h.19.e4b00b560d878dcfbc6635b3406640c5
0000000000000000 n wm4.stdlib.h.28.2cffa49d94c5d85f4538f55f7b59771d
0000000000000000 n wm4.stdlib.h.43.9fa4f727a2f1cb8d2450a574c9195553
0000000000000000 n wm4.stdlib.h.71.2927e068ec678159b4f68ec2f089f7e6
0000000000000000 n wm4.stubs64.h.10.918ceb5fa58268542bf143e4c1efbcf3
0000000000000000 n wm4.sysmacros.h.20.f376cf0587998a15dd322284414521cd
0000000000000000 n wm4.sysmacros.h.30.1c12047a18b4d58a289b6868436f8a56
0000000000000000 n wm4.sysmacros.h.52.9e2620974975a46f97a39f84517c176e
0000000000000000 n wm4.threadsharedtypes.h.78.de56fe19971b3f77b4f30b61727261f9
0000000000000000 n wm4.types.h.175.e5c9810a2b35492c3aae80a957d5f393
0000000000000000 n wm4.types.h.206.18407d3836aebf354b893f605f14800a
0000000000000000 n wm4.types.h.23.2d1642c69c19460d2bcb07f6ddc4852a
0000000000000000 n wm4.types.h.98.2414c985b07b6bc05c8aeed70b12c683
0000000000000000 n wm4.typesizes.h.24.292526668b3d7d0c797f011b553fed17
0000000000000000 n wm4.waitflags.h.25.41934de4af99038521c2782f418699b1
0000000000000000 n wm4.waitstatus.h.28.93f167f49d64e2b9b99f98d1162a93bf
0000000000000000 n wm4.wordsize.h.4.baf119258a1e53d8dba67ceac44ab6bc

main

000000000000085d T add
0000000000202010 B __bss_start
0000000000202010 b completed.7641
                 w __cxa_finalize@@GLIBC_2.2.5
0000000000202000 D __data_start
0000000000202000 W data_start
0000000000000a28 T deleteAll
0000000000000660 t deregister_tm_clones
00000000000006f0 t __do_global_dtors_aux
0000000000201da8 t __do_global_dtors_aux_fini_array_entry
0000000000202008 D __dso_handle
0000000000201db0 d _DYNAMIC
0000000000202010 D _edata
0000000000202018 B _end
0000000000000bd4 T _fini
0000000000000730 t frame_dummy
0000000000201da0 t __frame_dummy_init_array_entry
0000000000000e24 r __FRAME_END__
                 U free@@GLIBC_2.2.5
0000000000201fa0 d _GLOBAL_OFFSET_TABLE_
                 w __gmon_start__
0000000000000be8 r __GNU_EH_FRAME_HDR
000000000000076a T hashFun
00000000000005b8 T _init
0000000000201da8 t __init_array_end
0000000000201da0 t __init_array_start
0000000000000be0 R _IO_stdin_used
                 w _ITM_deregisterTMCloneTable
                 w _ITM_registerTMCloneTable
0000000000000bd0 T __libc_csu_fini
0000000000000b60 T __libc_csu_init
                 U __libc_start_main@@GLIBC_2.2.5
0000000000000779 T main
                 U malloc@@GLIBC_2.2.5
0000000000000816 T prepareHashTable
                 U printf@@GLIBC_2.2.5
000000000000073a T printInt
0000000000000ab9 T printValue
00000000000006a0 t register_tm_clones
                 U __stack_chk_fail@@GLIBC_2.4
0000000000000630 T _start
0000000000202010 D __TMC_END__

nm po lib_hash.a daje to samo co hash.o

0

adresy moich funkcji w wynikowej binarce roznia sie od tych w plikach .o, rozumiem, ze to jest zle i powinny byc takie same?

0

Nie, nie muszą.

1

Jeszcze jeden koncept... Pokaż całość z podziałem na pliki. Może coś jest namieszane z nazwami?

0

main.c

#include <stdio.h>

typedef int my_int;

void printInt(void *e) {
    my_int *tmp;
    tmp = (my_int *) e;
    printf("%d ", *tmp);
}

int generateHashInt(void *value) {
    return 2;
}

int main() {
    struct hash_table *table = NULL;

    table = prepareHashTable(generateHashInt, printInt);

    int a = 10;
    int b = 11;
    int c = 12;
    add(table, (void *) &b);
    add(table, (void *) &c);
    printValue(table, (void *) &a);

    return 0;
}

hash.c

#include <stdio.h>
#include <stdlib.h>

struct list_struct {
    void *value;
    struct list_struct *next;
};

struct hash_elem {
    struct list_struct *values;
    struct hash_elem *next;
    int key;
};

struct hash_table {
    struct hash_elem *first;

    int (*hashFun)(void *);

    void (*printFun)(void *);
};


struct hash_table *prepareHashTable(int(*hashFun)(void *), void(*printFun)(void *)) {
    struct hash_table *table = (struct hash_table *) malloc(sizeof(struct hash_table));
    table->first = NULL;
    table->printFun = printFun;
    table->hashFun = hashFun;
    return table;
}

void add(struct hash_table *hashTable, void *value) {
    int hashValue = hashTable->hashFun(value);
    if (hashTable->first == NULL) {
        hashTable->first = (struct hash_elem *) malloc(sizeof(struct hash_elem));
        hashTable->first->next = NULL;
        hashTable->first->key = hashValue;
        hashTable->first->values = (struct list_struct *) malloc(sizeof(struct list_struct));
        hashTable->first->values->value = value;
        hashTable->first->values->next = NULL;

        return;
    }

    struct hash_elem *hashElem = hashTable->first;
    while (hashElem->key != hashValue) {
        if (hashElem->next != NULL)
            hashElem = hashElem->next;
        else {
            hashElem->next = (struct hash_elem *) malloc(sizeof(struct hash_elem));
            hashElem->next->values = NULL;
            hashElem->next->next = NULL;
            hashElem->next->key = hashValue;
            hashElem = hashElem->next;
        }
    }

    if (hashElem->values == NULL) {
        hashElem->values = (struct list_struct *) malloc(sizeof(struct list_struct));
        hashElem->next = NULL;
        hashElem->values->next = NULL;
        hashElem->values->value = value;
        return;
    }

    struct list_struct *listElem = hashElem->values;

    while (listElem->next != NULL) {
        listElem = listElem->next;
    }
    listElem->next = (struct list_struct *) malloc(sizeof(struct list_struct));
    listElem->next->next = NULL;
    listElem->next->value = value;

}

void deleteAll(struct hash_table *hashTable) {
    struct hash_elem *hashElems = hashTable->first;
    struct hash_elem *hashElems2;
    struct list_struct *values2;
    struct list_struct *values;
    while (hashElems != NULL) {
        hashElems2 = hashElems->next;
        values = hashElems->values;
        while (values != NULL) {
            values2 = values->next;
            free(values);
            values = values2;
        }
        free(hashElems);
        hashElems = hashElems2;
    }
    free(hashTable->first);
    hashTable->first = NULL;

}


void printValue(struct hash_table *hashTable, void *value) {
    int hash = hashTable->hashFun(value);

    if (hashTable->first == NULL)
        return;

    struct hash_elem *tmp = hashTable->first;
    while (tmp->key != hash) {
        tmp = tmp->next;
        if (tmp == NULL)
            return;
    }

    struct list_struct *tmp2 = tmp->values;

    while (tmp2 != NULL) {
        hashTable->printFun(tmp2->value);
        tmp2 = tmp2->next;
    }
}


0

A nagłówek od tego hash.c (tzn. hash.h) to gdzie masz?

0

nie mam wcale .h bo kiedys gdzies czytalem, ze w przypadku tworzenia biblioteki statyczniej nie bedzie ona konieczna, ale dla sprawdzenia zrobilem wlasnie hash.h i niestety problem pozostal :| dzieki wgl za wytrwalosc

1

Nie ma za co, ciekawi mnie problem po prostu...
BTW. SuSE Tumbleweed, gcc 7.2.1, wszystko gra i buczy. Coś to Ubuntu 17 jakieś niewydarzone chyba.

1

Jeszcze mam jeden pomysł... spróbuj wywołać ar: ar rcs lib_hash.a hash.o zamiast tego co tam robisz wcześniej. Wątpię, że to pomoże, ale a nuż...

0

kurdee, to moze faktycznie te cholerne ubuntu17, ktore juz mnie irytuje m.in przez wayland ktory zawiesza mi system podczas korzystania z niektorych aplikacji jak np. vlc media player

wielkie dzieki za pomoc, jutro sprawdze na innym systemie jeszcze i sie odezwe czy zadzialalo :D

0

na fedorze działa...

1 użytkowników online, w tym zalogowanych: 0, gości: 1