1

I'm pretty new to C, and wanted to create a shared library for learning purposes. I have valgrind output below (Invalid read of size 8), but I am unsure where to look for the problem (hence, I can't recognize what the problem is).

My question is whether I can get kind souls to have a look and let me know where I'm going wrong.

My .c file:

#include <stdio.h>

int mult (int x, int y){
    return x * y;
}

void speak (const char* str){
    printf("%s\n", str);
}

unsigned char* arr (){
    unsigned char* list;

    int i;

    for (i=0; i<3; i++){
        list[i] = i;
    }

    return list;
}

My header file:

int mult (int x, int y);
void speak (const char* str);
unsigned char* arr ();

My entry point file:

#include <stdio.h>
#include "xswrap.h"

void main (){
    int ret = mult(5, 5);
    printf("%d\n", ret);

    speak("hello, world!");

    unsigned char* list = arr(); 

    int i;

    for (i=0; i<3; i++){
        printf("%d\n", list[i]);
    }
}

My compilation steps:

gcc -c -fPIC xswrap.c
gcc -shared -fPIC -Wl,-soname,libxswrap.so -o libxswrap.so xswrap.o -lc
gcc -o test main.c -L. -lxswrap

Output:

25
hello, world!
0
1
2
Segmentation fault

Valgrind output:

==13410== Memcheck, a memory error detector
==13410== Copyright (C) 2002-2015, and GNU GPL'd, by Julian Seward et al.
==13410== Using Valgrind-3.11.0 and LibVEX; rerun with -h for copyright info
==13410== Command: ./test
==13410== 
==13410== Invalid read of size 8
==13410==    at 0x4010C13: _dl_fini (dl-fini.c:235)
==13410==    by 0x5075FF7: __run_exit_handlers (exit.c:82)
==13410==    by 0x5076044: exit (exit.c:104)
==13410==    by 0x505C836: (below main) (libc-start.c:325)
==13410==  Address 0x620f08 is not stack'd, malloc'd or (recently) free'd
==13410== 
==13410== 
==13410== Process terminating with default action of signal 11 (SIGSEGV)
==13410==  Access not within mapped region at address 0x620F08
==13410==    at 0x4010C13: _dl_fini (dl-fini.c:235)
==13410==    by 0x5075FF7: __run_exit_handlers (exit.c:82)
==13410==    by 0x5076044: exit (exit.c:104)
==13410==    by 0x505C836: (below main) (libc-start.c:325)
==13410==  If you believe this happened as a result of a stack
==13410==  overflow in your program's main thread (unlikely but
==13410==  possible), you can try to increase the size of the
==13410==  main thread stack using the --main-stacksize= flag.
==13410==  The main thread stack size used in this run was 8388608.
==13410== 
==13410== HEAP SUMMARY:
==13410==     in use at exit: 0 bytes in 0 blocks
==13410==   total heap usage: 1 allocs, 1 frees, 4,096 bytes allocated
==13410== 
==13410== All heap blocks were freed -- no leaks are possible
==13410== 
==13410== For counts of detected and suppressed errors, rerun with: -v
==13410== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)
Segmentation fault
stevieb
  • 9,065
  • 3
  • 26
  • 36
  • 3
    `list` is not initialized, so `list[i]` (which means `*(list + i)` is reading an uninitialized value, which is UB. – Kerrek SB Mar 15 '17 at 23:09
  • 1
    You must allocate `list`. – DYZ Mar 15 '17 at 23:09
  • So, this question had me use `malloc()` for the first time, had me realize that `(m|c)alloc()` uses `char` as the size by default, and learn that `-Wall` is very important. I'm pleased :) – stevieb Mar 15 '17 at 23:36

2 Answers2

1

You never allocate memory for unsigned char* list, that has nothing to do with the fact that you are linking against a shared library.

list points to a garbage address, try by allocating it first:

unsigned char* list = malloc(3);

Mind that you must take care of freeing when it's no longer required through free(list).

Jack
  • 131,802
  • 30
  • 241
  • 343
  • ...and after a quick look, `malloc()` allocates in bytes, which what an unsigned char is, which is why you didn't use `sizeof(thing)` I assume. – stevieb Mar 15 '17 at 23:18
  • 1
    it's guaranteed by the standard, see http://stackoverflow.com/questions/2215445/are-there-machines-where-sizeofchar-1-or-at-least-char-bit-8 – Jack Mar 15 '17 at 23:20
  • 1
    True, the allocation unit for malloc is the char, it is a good habit to always define allocation unit though. – SegFault Mar 15 '17 at 23:21
  • Thank you Jack. I'm accepting this one because you referenced `free()`. – stevieb Mar 15 '17 at 23:21
  • @SegFault re: specifying the alloc unit, yeah, that's how I think I've always seen it done, so I'm going to stick to that. However, I've learned two new things here, one of which is if I see C code in the future without specifying the unit size within a `malloc/calloc()` call, it may be a red flag, and to check what is actually being allocated to. – stevieb Mar 15 '17 at 23:29
1

Why not allocating list:

unsigned char* list;
list = malloc(sizeof (unsigned char) * 3);

This will reserve space in memory to access list[i].

SegFault
  • 1,097
  • 1
  • 14
  • 14