-1

I'm not quite sure I get how malloc works exactly.

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

int main() {

 char * string = (char*) malloc(sizeof(char));
 string = "abc";

 int * test = (int*) malloc(1 * sizeof(int));
 *(test) = 5;
 *(test + 1) = 6;


}

I expected this to output an error since the value I appoint to string is bigger than just one char yet it seems to compile just fine.

I have a few questions:

  1. Where would 'string' be saved now? is it on memory spaces on the heap after the one space I allocated ?

  2. Why is does the char let me appoint directly and the int only via pointer?

I'm really not sure what I'm doing here

trincot
  • 317,000
  • 35
  • 244
  • 286
DarkInc
  • 11
  • 1
  • 1
    Why are you [casting the return value of malloc](http://stackoverflow.com/questions/605845/do-i-cast-the-result-of-malloc)? – PaulMcKenzie Jan 23 '17 at 10:38
  • @PaulMcKenzie I'm following a MIT ocw course and the ppt example used this but your right this seems pretty stupid thanks for the extra information – DarkInc Jan 23 '17 at 10:51
  • `*(test + 1) = 6;` writes out of bounds – M.M Jan 23 '17 at 11:04
  • What you are writing is undefined behavior. To be honest, if you don't know how to properly assign a string to a character pointer, you really aren't ready for `malloc`. – David Hoelzer Jan 23 '17 at 11:14
  • 2
    @DavidHoelzer No one was ready for `malloc`, let's be honest. – RoadRunner Jan 23 '17 at 12:05
  • @DavidHoelzer It might have been a little bit too ambitious of me considering I've only programmed a few small projects in garbage collected languages :) – DarkInc Jan 23 '17 at 12:50

6 Answers6

4

This code

string = "abc";

assigns the address of the string constant "abc" to the string variable, which is a char *. The address of the memory returned from your malloc() call - which was in string - gets overwritten and lost.

Andrew Henle
  • 32,625
  • 3
  • 24
  • 56
2

Where would 'string' be saved now?

char * string = (char*) malloc(sizeof(char));
string = "abc";

string now points to "abc" (a literal string) - the initial dynamic allocation (in the heap) has been lost track and you have a memory leak.

artm
  • 17,291
  • 6
  • 38
  • 54
2

In addition to the other answers:

You probably want this:

char *string = (char*) malloc(sizeof(char) * 100);  // allocate space for 100 chars
strcpy(string, "abc");  // copy the "abc" into the memoory location pointer by string

instead of this:

char *string = (char*) malloc(sizeof(char));   // << this allocates only a single char
string = "abc";

And

*(test) = 5;
*(test + 1) = 6;

is better written as:

test[0] = 5;
test[1] = 6;

which is strictly equivalent, it's just a matter of readability.

Allocating too few memory:

If you allocate memory for only 1 char as here:

char *string = (char*) malloc(sizeof(char));  // allocate space 1 char
strcpy(string, "abc");  // copy the "abc" into the memoory location pointer by string

then your program will still compile fine, but at runtime the string will be copied partly to non allocated memory, which results in undefined behaviour (google "undefined behaviour").

Jabberwocky
  • 48,281
  • 17
  • 65
  • 115
  • but I'm only allocating space for one char wouldn't it be possible then that when I allocate space for another variable that the adresses holding "bc\0" would be overwritten? EDIT: yeah you answered before my comment was finished thanks – DarkInc Jan 23 '17 at 10:41
  • Magic numbers are extremely bad practice. It's a bad idea to start new programmers off with bad habits. – David Hoelzer Jan 23 '17 at 11:15
  • @DavidHoelzer you are right, but I didn't want to overcomplicate things, the OP's program being just a test program anyway. – Jabberwocky Jan 23 '17 at 11:26
0

I will give you a real-life example.

Suppose Mr. A lives at the address "abc". Now, some Mr. B starts living at some address "xyz". Soon, Mr. B address "xyz" is renamed to "abc". Now, if you go to the address "abc", you will meet Mr. B, not Mr. A. But, this don't mean that Mr. A place is demolished. It simply means that Mr. A's living area now has no reachable address and is lost.

Similarly, the memory you malloc'ed to string and then re-assigned the string to "abc", means, string earlier had an address to the malloc'ed memory. Later, your "abc" is written to some memory and the address to that memory is stored in string. Thus, losing the malloc'ed memory forever which is called Memory Leak.

Abhineet
  • 5,320
  • 1
  • 25
  • 43
0

The compiler will not prevent you to do something that is allowed - however you're likely to get a warning for the 1) since string is assigned and not used before being re-assigned (provided that the compiler is requested to output the relevant warnings).

As for 2), you call a function which happens to be malloc, with an argument that happens to be too small for the usage you want to do with the pointer returned by malloc, but since the syntax is correct, the compiler doesn't complain.

Answer to

1) string points to "abc" and the previous value from malloc is lost

2) you could do test[0] = 5; as well.

The behavior for 2) is undefined behavior (access an array out of bounds).

Déjà vu
  • 28,223
  • 6
  • 72
  • 100
0

At first there was allocated dynamically memory with the requested size of one character.

char * string = (char*) malloc(sizeof(char));

And then the pointer was reassigned with the address of the first character of the string literal "abc".

string = "abc";

As result the address of the dynamically allocated memory was lost and there is a memory leak in the program.

If the program would written in C++ then this statement

string = "abc";

could arise a compiler diagnostic message because string literals in C++ have types of constant character arrays and the pointer string shuld be declared like

const char *string;

As for the string literal then they have static storage duration and are allocated before main gets the control. Usually all string literals are places in the so-called string literal pool.

Instead of this statement

string = "abc";

you could write

strcpy( string, "abc" );

In this case the program has undefined behavior. However it can continue to work successfully due to the feature that usually the function malloc allocates minimum memory extent equal to the value of the paragraph that is equal to 16 bytes.

Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
  • This is a C question. Behaviour of C++ code is irrelevant – M.M Jan 23 '17 at 10:53
  • @M.M There is no any "irrelevant" information. In C 1) pointers also can be declared with qualificator const that is in C can be used the same approach as in C++; 2) any comparison of the same construction in C and C++ are very useful and helps to understand better C and C++. – Vlad from Moscow Jan 23 '17 at 10:56