0

I have the following function:

void print_out_str(FILE* outstream, UINT x, int n) {

   assert(n >= 1);

   int n1, n2, j;

   n1 = (n - 1)/64; n2 = n % 64;
   for(j = 0; j <= n1 - 1; j++) 
      fprintf(outstream,"%016llx ",x[j]); //padding with 0
   fprintf(outstream,"%016llx ",x[n1] & ((1ULL<<n2) - 1ULL));

where "outstream" is where I'd like to print, UINT is a typedef for uint64_t* and n is a number of bits I want to print.

I don't understand why but every time i try to call such function the program crash with a segmentation fault. I've tried with GDB to understand if the variables content (outstream, x, n) is what i expect and it is fine. Specifically, as simple case i tried with an array of two elements, n = 87 and x[0] = x[1] = 0, outstream = stdout.

Am I missing something?

Update:

Some more info...

Here it is the code i call before the function i mentioned:

void test_set_bit() {
   int nbits_to_allocate, i;
   UINT x;

   printf("Set the size of your x var: "); scanf("%d",&nbits_to_allocate);
   init_ui(x,nbits_to_allocate);
   printf("Set the specific bit would you like to set: "); scanf("%d",&i);

   set_ui_zero(x,nbits_to_allocate);
   printf("Content before the bit set:\n");
   print_out_str(stderr,x,nbits_to_allocate);
   //Neglect the following three lines...
   //set_ui_bit(x,nbits_to_allocate,i); 
   //printf("Content after the bit set:\n");
   //print_out_str(stderr,x,nbits_to_allocate);

}

where init_ui is

void init_ui(UINT x, int n) {

   assert(n >= 1);

   int N;
   N = (n + 63)/64;
   x = (UINT)malloc(N*sizeof(uint64_t));
}
user8469759
  • 2,522
  • 6
  • 26
  • 50
  • 3
    [Couldn't reproduce](http://melpon.org/wandbox/permlink/i99KRzLcnTWfS3iJ). You may invoked *undefined behavior* by passing data having wrong type to `printf()`. You should use `"%"PRIx64` instead of `"%llx"` to print `uint64_t` and use `UINT64_C(1)` instead of `1ULL`. – MikeCAT Mar 15 '16 at 10:34
  • Try to simplify the function for debugging. At some point the error will no longer occur and that will give you a hint about how to proceed. – RhinoDevel Mar 15 '16 at 10:35
  • 1
    I added `assert()` to check out-of-range access, and [they didn't fail](http://melpon.org/wandbox/permlink/8st1NNJFxIrp3iSe). Please post a [Minimal, Complete, and Verifiable example](http://stackoverflow.com/help/mcve). – MikeCAT Mar 15 '16 at 10:36
  • 1
    You are passing an `UINT x`, and then you use `x`as a pointer `x[j]` etc. – Jabberwocky Mar 15 '16 at 10:41
  • indeed, how does this code even compile?! – Antti Haapala -- Слава Україні Mar 15 '16 at 10:42
  • I have to print the "dereferenced value..." so it's normal i use x[j] – user8469759 Mar 15 '16 at 10:42
  • I don't get what's the problem with my use of x. x is a pointer, x[j] is the value pointed at address x + j, since it is allocated there's no problem with that... and i want to print such value, I can't see the problem with that. – user8469759 Mar 15 '16 at 10:46
  • 1
    Note: They say [you shouldn't cast the result of `malloc()` in C](http://stackoverflow.com/questions/605845/do-i-cast-the-result-of-malloc). – MikeCAT Mar 15 '16 at 10:48
  • 1
    @lukkio `UINT` not only looks but is often **used** as a typedef for an **unsigned int type**, not **pointer to unsigned int**. – Antti Haapala -- Слава Україні Mar 15 '16 at 10:50
  • I'm getting confused... why i shouldn't perform the cast? and why my UINT is used as typedf to unsigned int type instead of a pointer? the typedef is: typedef uint64_t* UINT, and i use it as an array, after dinamic allocation, I still can't see the problem. Please elaborate more. – user8469759 Mar 15 '16 at 10:53
  • @lukkio: The cast is unnecessary, and under the C89 standard can suppress a warning if you forget to include `stdlib.h`. And hiding pointers behind typdefs is considered bad practice; I've lost more than one afternoon trying to figure out why some bit of code wouldn't compile, and it was because someone hid a pointer behind a typedef. Pointers are special, and pointer-ness should always be visible. – John Bode Mar 15 '16 at 12:28
  • Better to use `fprintf(outstream,"%016llx ",(unsigned long long) x[j]);` as `x[j]` is not known to be `unsigned long long`. – chux - Reinstate Monica Mar 15 '16 at 14:12
  • What should I use instead of "%llx"? – user8469759 Mar 15 '16 at 14:33

1 Answers1

5

In C, function arguments are passed by value and modifying them in callee won't affect caller's local variables. You invoked undefined behavior by using a value of uninitialized variable x having automatic storage duration, which is indeterminate.

Use pointers to have caller modify caller's local variables.

void init_ui(UINT *x, int n) { /* add * to declare pointer to UINT */

   assert(n >= 1);

   int N;
   N = (n + 63)/64;
   *x = malloc(N*sizeof(uint64_t)); /* add * to access what is pointed by x */
}

usage:

UINT x;

init_ui(&x,nbits_to_allocate); /* add & to get address of x */
MikeCAT
  • 73,922
  • 11
  • 45
  • 70
  • This make sense... let me give it a go, I still don't get the problem with the malloc casting. Is it for redundancy? – user8469759 Mar 15 '16 at 10:56