0

I'm watching a course online learning C and I stumbled upon something that is crashing my program. In the video they show the following code snippet :

#include <stdio.h>

int main()
{
    char* ch;
    int num = 12345;
    sprintf(ch, "%d", num);
    printf("%s\n", ch);
    return(0);
}

I've decided to make my own little program and test it. Here's the code I've written :

#include <stdio.h>

#define A 65

int main()
{
    int n = A;
    printf("n is equal to %d\n", n);
    n = atoi("10");
    printf("n is equal to %d\n", n);
    char* ch;
    sprintf(ch, "%d", n);
    printf("ch is equal to %s\n", ch);
    return 0;
}

When I run my program, the output is as follow :

n is equal to 65
n is equal to 10

After this part my program crashes. I assume the sprintf function is causing this but I'm not sure why, I'm new to the language so I wouldn't know, I think I've done everything correctly judging by the code snippets that was shown in the video. Could someone please explain me what I did wrong ?

Thanks in advance.

AALC
  • 93
  • 1
  • 2
  • 6
  • 2
    you haven't allocated any memory for `ch` – Cyclonecode Aug 25 '14 at 23:48
  • the var ch is a pointer. It must actually point to an available area. As it is, it is pointing to la la land, so using this uninitialized pointer can (but not always) cause a program crash. – user3629249 Aug 26 '14 at 03:36

3 Answers3

4

In the video they show the following code snippet: [...]

If this is a snippet that they say should work, stop watching that video: the snippet has undefined behavior, there is no chance that it would work properly unless by an unlucky coincidence.

I've decided to make my own little program and test it.

Your program has the same exact problem: the buffer to which sprintf is writing has not been initialized. Change the declaration of ch to allocate some space to it, like this:

char ch[20];

This will prevent your code from writing to memory pointed to by an uninitialized pointer, fixing the undefined behavior.

Could you explain to me how char* could be used?

If you would like to use char*, assign it a result of malloc of a proper size, and free the result at the end:

char *ch = malloc(20);
... // Put the rest of the code here
// Add this line before the end:
free(ch);
Sergey Kalinichenko
  • 714,442
  • 84
  • 1,110
  • 1,523
  • Ok, could you explain to me how char* could be used then ? – AALC Aug 25 '14 at 23:57
  • @dasblinkenlight char *ch = malloc(20) means we allocate 20 bytes to be used for this char, and char[20] means we allocate it actual 20 characters ? – AALC Aug 26 '14 at 00:03
  • @AALC Call of `malloc` allocates memory from the "free store" (AKA "the heap memory"), while `char ch[20]` makes an array of the same size (20 bytes) in the "automatic store" (AKA "on the stack"). You must `free` the free store memory, while automatic memory is freed, well, automatically. In all other respects, the two allocations are the same. – Sergey Kalinichenko Aug 26 '14 at 00:06
  • @dasblinkenlight Could you explain the differences between the heap memory and the stack ? I know it's starting to go off-topic but it interest me. – AALC Aug 26 '14 at 00:08
  • @AALC Take a look at [this answer](http://stackoverflow.com/a/15306893/335858), it's tagged about Objective-C, but it is really a C answer, because both languages use the same memory management system. – Sergey Kalinichenko Aug 26 '14 at 00:14
  • @dasblinkenlight I would've moved this discussion to a chat as suggested me by the site but I can't because of my low reputation in the site so please forgive me. So from your answer is it correct to say that in my code snippets A is allocated in the static area, n in the automatic area (the stack) and ch (although not allocated in my example) is allocated in the dynamic area (the heap) ? Also from my understanding the automatic area has a memory management system unlike the dynamic area which the coder have to manage the memory by himself and about the static Idon't really know the difference – AALC Aug 26 '14 at 00:21
  • But why would be 3 different areas in the first place ? The automatic seems the most reasonable (didn't have enough characters for my comment) – AALC Aug 26 '14 at 00:23
  • @AALC In your example, `A` is not allocated at all. It is a preprocessor constant, not a variable. It produces a textual substitution, and it does not consume any memory. You're right about the other two: `n` is automatic, and `ch` is free store. Automatic memory is freed when you leave the function; free store is freed when you call `free`. Static memory always exists: it is allocated when your program starts, and it is freed only when your program exits. – Sergey Kalinichenko Aug 26 '14 at 00:28
2

You need to alocate memory for ch or else use an array instead of a pointer.

char* ch = malloc(sizeyouwant * sizeof(char));

Where sizeyouwant is the number of characters you will store.

Mognom
  • 214
  • 1
  • 3
  • 1
    And if you're going to use malloc, don't forget to `free(ch)` when you're done. – William Everett Aug 25 '14 at 23:57
  • Thanks for the nice addition :) – AALC Aug 26 '14 at 00:09
  • @AALC: Never use `sizeof(char)`, it's not enough to guard against 1 not being 1 anymore. – Deduplicator Aug 26 '14 at 00:18
  • @Mognom I've changed this line to the following : char* ch = malloc(20 * sizeof(char)); and I get an error while compiling "warrning: incompatible implicit declaration of built-in function 'malloc' [enabled by default]" – AALC Aug 26 '14 at 00:35
  • @AALC You are missing the library of `malloc()` and `free()`, which is stdlib.h. You just need to include it. – Mognom Aug 26 '14 at 12:12
0

The problem is here:

char* ch;

this is just a char pointer, it needs to point to allocated memory to hold the string:

char ch[32];
thumbmunkeys
  • 20,606
  • 8
  • 62
  • 110
  • `char ch[32]` means that `ch` is no longer a pointer. It's a valid solution (assuming 32 is enough space), but your description is incorrect. – Keith Thompson Aug 25 '14 at 23:51
  • `ch` is still a pointer. If you do something like `char ch[4]="the"` and then `printf("%c", *s)` you will print `t`. Likewise, try `printf("%p %p",s,&s)` and you'll get the same address printed out twice. In c, the name of an array points to the location of the zeroth element and the index at the end is a kind of shorthand so that `ch[n]` points to the same place as `*(ch + n * sizeof(char))` in memory. – William Everett Aug 26 '14 at 00:11