so I'm quite new in this, sorry if it sound like a dumb question
I'm trying to understand malloc, and create a very simple program which will print "ABC" using ASCII code
here is my code (what our professor taught us) so far
char *i;
i = malloc(sizeof(char)*4);
*i = 65;
*(i+1) = 66;
*(i+2) = 67;
*(i+3) = '\0';
what I don't understand is, why do I have to put malloc there?
the professor told us the program won't run without the malloc,
but when I tried and run it without the malloc, the program run just fine.
so what's the function of malloc there?
am I even using it right?
any help and or explanation would be really appreciated
the professor told us the program won't run without the malloc
This is not quite true, the correct wording would be: "The program's behavior is undefined without malloc()".
The reason for this is that
char *i;
just declares a pointer to a char, but there's no initialization -- this pointer points to some indeterminate location. You could be just lucky in that writing values to this "random" location works and won't result in a crash. I'd personally call it unlucky because this hides a bug in your program. undefined behavior just means anything can happen, including a "correct" program execution.
malloc() will dynamically request some usable memory and return a pointer to that memory, so after the malloc(), you know i points to 4 bytes of memory you can use. If malloc() fails for some reason (no more memory available), it returns NULL -- your program should test for it before writing to *i.
All that said, of course the program CAN work without malloc(). You could just write
char i[4];
and i would be a local variable with room for 4 characters.
Final side note: sizeof(char) is defined to be 1, so you can just write i = malloc(4);.
Unfortunately, "runs fine" criterion proves nothing about a C program. Great deal of C programs that run to completion have undefined behavior, which does not happen to manifest itself on your particular platform.
You need special tools to see this error. For example, you can run your code through valgrind, and see it access uninitialized pointer.
As for the malloc, you do not have to use dynamic buffer in your code. It would be perfectly fine to allocate the buffer in automatic memory, like this:
char buf[4], *i = buf;
You have to allocate space for memory. In the example below, I did not allocate for memory for i, which resulted in a segmentation fault (you are trying to access memory that you don't have access to)
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(void)
{
char *i;
strcpy(i, "hello");
printf("%s\n", i);
return (0);
}
Output: Segmentation fault (core dumped)
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(void)
{
char *i;
/*Allocated 6 spots with sizeof char +1 for \0 character*/
i = malloc(sizeof(char) * 6);
strcpy(i, "hello");
printf("%s\n", i);
return (0);
}
Result: hello
Malloc allows you to create space, so you can write to a spot in memory. In the first example, "It won't work without malloc" because i is pointing to a spot in memory that doesn't have space allocated yet.
Related
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void foo() {
char *a_heap_pointer;
a_heap_pointer = (char*)malloc(1 * sizeof(char));
strcpy(a_heap_pointer, "a");
printf("%s\n", a_heap_pointer);
while (1){
++a_heap_pointer;
a_heap_pointer = (char*)malloc(1 * sizeof(char));
strcpy(a_heap_pointer, "b");
printf("%s\n", a_heap_pointer);
}
}
int main (void) {
foo();
return 0;
}
Hi there, I'm trying to make my C program cause a segmentation fault by incrementing a pointer that points at the heap, by 1 byte, repeatedly, until the program crashes. However, as my code stands now it just runs indefinitely? I presume because the heap is so large that it would take awhile for it to run out. How can I make my program break the heap?
Printing on the screen is very slow compared to in-memory operations, so if you remove the printfs, you will probably not have to wait as long.
But modern computers have a lot of memory, and when you take into account swap space on disk it can be many hundreds of gigabytes. Prepare to wait for a long time.
Also, in C, strings are NUL-terminated, so the strings "a" and "b" both require two chars storage. Therefore your calls to strcpy overwrite memory that may be used for other things, so your program's behaviour is undefined. Anything can happen, for example that it gets stuck and never terminates.
And a side note: I'm not sure what effect you expect ++a_heap_pointer; to have? You increment that pointer, but then you immediately replace the incremented value by the return value from malloc, so the result of the increment operation will never be used.
What are the possible behaviors of the program below?
I have tried to allocate and use memory on stack,
and print the memory block pointed by p, output are characters of '\0'.
I known technically it is not available when the function returns.
However, why not the program crash, or print some random garbage?
#include <cstring>
#include <cstdio>
#include <cstdlib> //malloc
char* getStackMemory(){
char mem[10];
char* p = mem;
return p;
}
int main(){
char* p = getStackMemory();
strcpy(p, "Hello!");
printf("%s\n", p);
for(int i = 0; i<10; i++){
printf("%c\n", p[i]);
}
return 0;
}
As per you already know that memory of char mem[10]; on stack and it is not available when the function returns. So i only says that it will cause you Undefined Behavior.
why not the program crash, or print some random garbage?
The program will not crash as you are not accessing any illegal memory. The stack memory is a part of your program and as long as you are accessing the memory in a valid range the program will not crash. Yes, you can modify the stack memory whether the function is in that stack frame or not.
Now accessing the memory which is not in the current stack frame will lead to an Undefined Behavior. This is compiler dependent. Most of the compiler will print the garbage value. I don't know which compiler you are using!!
I would say try to understand the basic concept of stack memory in C/C++ programs. An I would suggest also look into heap memory.
It is because after the function returns, the stack is unavailable however u r returning the address of that location from that function which is getting stored in pointer p, so the program does not crash but gives garbage value.
Here, the program will not crash rather it will print some garbage value. When it will return stack will not be available and hence will give garbage value.
I am very new to both using Linux and creating anything remotely serious on C. I've been trying to create a program which will simply compress a single string, but I keep getting this Segmentation fault when trying to run the compiled file.
I compiled it using:
gcc 2.c -o test.o -lz
My code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <zlib.h>
#include <assert.h>
int main ()
{
char *istream = malloc(10), *ostream = malloc(120);
istream = "istream";
int res = compress(ostream, (uLongf *)strlen(ostream), istream,(ulong)strlen(istream));
return 0;
}
Could anyone explain to me why this error is happening and how can I improve my code?
This line would appear to be the main problem:
(uLongf*)strlen(ostream)
You are interpreting a size_t value as a pointer to a buffer. You are meant to pass the address of an unsigned long containing the length of the output buffer. Take another look at the documentation for compress.
On top of that you don't yet understand how C strings work. The assignment operator when used with a char* lvalue merely copies an address and not the contents of a string. I suggest that you declare your buffers like this:
const char *istream = "istream";
char ostream[120];
I think your program should be something along these lines:
int main(void)
{
const char *istream = "istream";
char ostream[120];
uLongf destLen = sizeof(ostream);
int res = compress((Bytef*)ostream, &destLen, (Bytef*)istream, strlen(istream));
return 0;
}
Note that I wrote the code assuming that you are using a C compiler. And hence int main(void).
First you make istream point to memory you allocate:
char *istream = malloc(10)
then you make it point to a literal (and therefore constant and read-only) string:
istream = "istream";
You need to copy the string literal into the allocated memory, or you will no longer have the original pointer you allocated and have a memory leak. You also will not be able to free that pointer, since istream points to something you haven't allocated with malloc.
As for the crash, see the answer by David Heffernan.
As a side-note, there is no C++ in your code, only pure and plain C.
Change:
istream = "istream"
To
strcpy(istream,"istream");
In addition, what did you expect strlen(ostream) to return? 120?
strlen returns the index of the first 0 character encountered within the input string.
In your case, the contents of the memory pointed by ostream is unknown (i.e. "junk").
strlen will scan this memory until a 0 character is encountered, but will probably exceed the 120-byte memory space and cause a memory access violation.
Change strlen(ostream) to 120 if that was your intention.
My code:
#include <stdio.h>
#include <stdlib.h>
int main(void) {
int *p = (int *)malloc(sizeof(int));
free(p);
*p = 42;
return 0;
}
I created a pointer, then I pointed it to allocated space and finally I had assigned 42 to it.
In my opinion it should not work, it should cause a segmentation fault, but it works.
So, why?
PS: I normally compiled it with Gcc on Linux
Pure luck. The behavior in this case is undefined. I.e.: no expectations can be made as to what may happen.
In my opinion it should not work [...] but it works.
Don't worry, it doesn't work.
it should cause a segmentation fault
Tell that to the C standards committee. It's just undefined behavior, it isn't required to crash.
The more elaborate answer beyond "undefined" is that you can write to arbitrary memory locations in C as long as you stay within the processes allocated memory areas. Depending on OS, overwriting code may be allowed or not. The ill effects only turn up, once some other code of your process gets confused by what is found at the garbled memory location. Since your program exits right away after messing up the memory, the chance for some of its code to get confused is obviously small.
The behavior in this case is undefined ,
it is a possibility with undefin behavior
you display the memory address of p before and after free to check "p" with :
#include <stdio.h>
#include <stdlib.h>
int main(void) {
int *p = (int *)malloc(sizeof(int));
printf("before \n %p \n",p);
free(p);
*p = 42;
printf("after\n %p \n",p);
printf(" %d \n",*p);
return 0;
}
before and after free we have the same address memory because free() don't assign NULL to p pointer, so *p = 42; work like static assignment although it's undefined behaviour.
suggest to use the FREE macro :
#define FREE(X) \
free(X);\
X=NULL;
test with this macro and you will see the expected behaviour
I have seen some differences in the result of the following code:
#include <stdio.h>
#include <malloc.h>
#include <string.h>
int main(void)
{
char* ptr;
ptr = (char*)malloc(sizeof(char) * 12);
strcpy(ptr, "Hello World");
printf("%s\n", ptr);
printf("FREEING ?\n");
free(ptr);
printf("%s\n", ptr);
}
Let me explain:
In the third call to printf depending the OS I get different results, gargabge caracters in Windows, nothing in Linux and in A Unix system "Hello World" is printed.
Is there a way to check the status of the pointer to know when memory has been freed?
I think this mechanism of print can not be trusted all the times.
Thnaks.
Greetings.
Using a pointer after it has been freed results in undefined behavior.
That means the program may print garbage, print the former contents of the string, erase your hard drive, or make monkeys fly out of your bottom, and still be in compliance with the C standard.
There's no way to look at a pointer and "know when memory has been freed". It's up to you as a programmer to keep track.
If you call free(), the memory will have been freed when that function returns. That doesn't mean that the memory will be overwritten immediately, but it's nevertheless unsafe to use any pointer on which you've called free().
It's a good idea to always assign nil to a pointer variable once you've freed it. That way, you know that non-nil pointers are safe to use.
Simple ansewr: you can't check if a pointer has been freed already in C. Different behaviors are probably due to different compilers, as using a pointer after freeing it is undefined you can get all sorts of behavior (including a SEGFAULT and program termination).
If you want to check if you use free property and your program is memory leak free, then use a tool like Valgrind.