0

I am new to C and this is my first post here.

My attempts to fix this bug, and other bugs I had, have left this code scrambled, so do keep that in mind. My program reads from the user a complex number and, depending on the command, stores it, or prints it, in one of six typedefed complex struct {double d1, d2; char *val;} globally-declared vars (A to F).

GDB leads me to the free at the bottom and from what I've seen it sometimes frees the input and sometimes it doesn't, for some odd reason it also depends what var I select as the example below shows. Note that remove_space_tab is of void type and modifies the original user input from the address malloc returned. It's probably a silly beginner's mistake, something with the memory I guess.

:
read_comp A, 2.56, -1.32

0x908f068   read_compA,2.56,-1.32

0x908f008   0.00+0.00i // this 4 lines are from printf's that extend to readComp function

0x908f008  // 

0x908f008  //

0x908f008   2.56+(-1.32)i //

0x908f068   read_compA,2.56,-1.32

(nil)   (null)

Enter a command:
read_comp F, 5.61, -7.56

0x908f068   read_compF,5.61,-7.56

0x908f058   0.00+0.00i //

0x908f058 //

0x908f058 //

0x908f058   5.61+(-7.56)i // F does free the initialised val and sets the user input as the new val

0x908f068   read_compF,5.61,-7.56 // doesn't free this 
*** glibc detected *** ./mycomp: double free or corruption (!prev):
0x0908f068

int main() {

  A.d1 = 0;
  A.d2 = 0;
  B.d1 = 0;
  B.d2 = 0;
  C.d1 = 0;
  C.d2 = 0;
  D.d1 = 0;
  D.d2 = 0;
  E.d1 = 0;
  E.d2 = 0;
  F.d1 = 0;
  F.d2 = 0;

  A.val = (char*) malloc(12 * sizeof(char));
  B.val = (char*) malloc(12 * sizeof(char));
  C.val = (char*) malloc(12 * sizeof(char));
  D.val = (char*) malloc(12 * sizeof(char));
  E.val = (char*) malloc(12 * sizeof(char));
  F.val = (char*) malloc(12 * sizeof(char));

  sprintf(A.val, "%.2lf+%.2lfi", A.d1, A.d2);
  sprintf(B.val, "%.2lf+%.2lfi", B.d1, B.d2);
  sprintf(C.val, "%.2lf+%.2lfi", C.d1, C.d2);
  sprintf(D.val, "%.2lf+%.2lfi", D.d1, D.d2);
  sprintf(E.val, "%.2lf+%.2lfi", E.d1, E.d2);
  sprintf(F.val, "%.2lf+%.2lfi", F.d1, F.d2);

  while (1) {
    input = malloc(30 * sizeof(char));
    printf("\nEnter a command:\n");
    gets(input);
    remove_space_tab(input);
    printf("\n%p   %s\n", input, input);

    if (strncmp(input, "stop", 4) == 0 && *(input + 4) == '\0') {
      break;
    } else if (strncmp(input, "stop", 4) == 0 && *(input + 4) != '\0') {
      printf("Extraneous text after end of command.");
      break;
    }
    if (strncmp(input, "read_comp", 9) == 0) {
      input += 9;
      readComp(input);
      input -= 9;
    }

    if (strncmp(input, "print_comp", 10) == 0) {
      if (!('A' <= *(input + 10) && 'F' >= *(input + 10))) {
        printf("\nUndefined complex variable.\n");
        break;
      }
      if (*(input + 11) != '\0') {
        printf("\nExtraneous text after end of command.\n");
        break;
      }
      printComp(input[10]);
    }

    printf("\n%p   %s\n", input, input);
    free(input);
    input = NULL;
    if (input != NULL) {
      printf("Memory could not be allocated.");
      break;
    }
    printf("\n%p   %s\n", input, input);

  }

  return 0;
}
chqrlie
  • 131,814
  • 10
  • 121
  • 189
Elbaz
  • 19
  • 2
  • There is definitely unfreed memory here. None of `A.val`, `B.val`, etc. are being freed. And if any of the `break` statements that precede `free(input);` are executed, you will leak the memory pointed to by `input`. – Tom Karzes Sep 11 '20 at 23:14
  • But A.val to F.val are getting malloc once and when I get to them in readComp I free the selected var of the initialised value first and then I malloc the var again and then set it with the user input as the new one and from what I've seen it works and what GDB has shown me. You can see this in the example above. It's the last free that's problematic. – Elbaz Sep 11 '20 at 23:20
  • 1
    Finding the memory corruption is the bigger problem. But note that the final `printf` is guaranteed to to fail, since `input` is `NULL` at that point and you're trying to use a `%s` format with it, which will attempt to dereference the `NULL` pointer. Just get rid of the second format and argument. – Tom Karzes Sep 12 '20 at 00:05
  • Post definition of globally-declared vars ( A to F). – chux - Reinstate Monica Sep 12 '20 at 07:10
  • chux, I already did. – Elbaz Sep 12 '20 at 11:27
  • 1
    Since most likely, the problem is inside functions not shown here (e.g. `readComp()`), it is hard to help. My guess would be, that inside readComp(), you make the mistake to store away a pointer to input, then you free input later on and after that, you free the pointer inside a complex number (which used to be a pointer to input). – BitTickler Sep 12 '20 at 12:11
  • Never use `gets`. It can cause a buff-overflow problem. – wxk1997 Sep 14 '20 at 10:56

1 Answers1

0

At least this problem.

In last line, input == NULL and using "%s" with that is undefined behavior (UB).

// printf("\n%p   %s\n", input, input);
printf("\n%p\n", input);
chux - Reinstate Monica
  • 143,097
  • 13
  • 135
  • 256
  • Then why in the example when the var is A it works and prints nil and null? and even if I remove it, it still prints an error. – Elbaz Sep 12 '20 at 11:25
  • If this helps, it also prints Program received signal SIGABRT, aborted some address in __kernel_vsyscall (). – Elbaz Sep 12 '20 at 11:42
  • 1
    See [Undefined, unspecified and implementation-defined behavior](https://stackoverflow.com/q/2397984/3422102). What happens after UB is invoked is simply **Undefined**. It can do anything from appear to work normally to SegFault or anything inbetween. Further `malloc(12)` is all that is needed. It is unnecessary to cast the return and `sizeof(char)` is defined as `1`. – David C. Rankin Sep 12 '20 at 12:11
  • David C Ranking. But I still don't understand why C sometimes frees the memory and sometimes doesn't want to free the memory I allocated to input, and both the free and malloc are together in a loop inside of main, and not mentioned anywhere else in my program. As I said before, the pointer that was given to me for input is the same as the one in free ( checked that by printing the addresses ) Don't know man, the syntax in C is so convoluted. It is hard for me to grasp my head around it. – Elbaz Sep 12 '20 at 12:48