I have a method called printNums, where I would like to print integers from 1 - 10. For my assignment, I'm supposed to malloc an int pointer, set it, pass in to my function as a void* point and inside the function, cast it, deference it and print that integer out before each iteration of the counter.
However, I keep getting a segmentation fault after *((int*)ptr) and I'm not too sure why. Any help would be appreciated.
Here is my code:
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
void* printNums(void *ptr);
int main(int argc, char **argv)
{
int *ptr = (int*)malloc(sizeof(int));
ptr = 0;
printNums(ptr);
return 0;
}
void* printNums(void *ptr){
int i = 0;
for (i = 0; i <= 10; i++){
*((int*)ptr) = i;
printf("%d\n", *((int*)ptr));
}
}
You're assigning ptr pointer to zero.
change ptr = 0; to *ptr = 0;.
You are resetting the address to zero:
ptr = 0;
Which means you will definitely (in most environments and operating systems) get a segmentation fault if you try to access it.
I think you wanted to set the value pointed by ptr to 0 before you can use, so by mistake you made ptr = 0
to make all the values pointed by ptr to be 0 you need to use memset
memset(ptr,0,sizeof(int));
However, I keep getting a segmentation fault after *((int*)ptr) and
I'm not too sure why.
You can try to find out yourself. Programming requires some debugging skills - forums are not the replacement.
void* printNums(void *ptr){
int i = 0;
for (i = 0; i <= 10; i++){
printf("%p\n", ptr);
//*((int*)ptr) = i;
//printf("%d\n", *((int*)ptr));
}
return ptr;
}
https://godbolt.org/z/EYhGKn
and the output
(nil)
(nil)
(nil)
(nil)
(nil)
(nil)
(nil)
(nil)
(nil)
(nil)
(nil)
And the answer is obvious: you dereference NULL pointer.
Now you can try to find out why you pass the NULL pointer to the function. As the program is 12 lines long it will not take too much time to discover the line:
ptr = 0;
Which assigns integer zero to the pointer. So the pointer is now NULL.
Related
I'm new to dynamic memory, I'm trying to learn.
I keep getting in my codes "Process finished with exit code 11".
this is one code:
int main()
{
int *p;
printf("%d",&p);
p = (int)malloc(sizeof(int));
if(p==NULL)
{
printf("failed");
free(p);
exit(1);
}
printf("%d",p);
*p = 4;
printf("%d",*p);
return 0;
}
p = (int)malloc(sizeof(int));
This is not right. malloc returns a pointer (void *) and p is a pointer; there is no need to cast at all, and certainly not to int. If you are very lucky, the cast to int may simply have no effect. If you are unlucky, such as on machines where pointers are 64 bits and int is 32 bits, you'll end up with an incorrect pointer, or some other form of undefined behavior.
A couple other bugs:
You should use the %p format specifier to print pointers, not %d. And you probably want to include spaces or newlines after the values you print, otherwise they'll all run together and be hard to read.
It's good that you check whether malloc succeeded or failed, but if it failed, there is no point in calling free on the null pointer that was returned. free(NULL) is defined as doing nothing.
Here's a corrected version of your program (try on godbolt):
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
int *p;
printf("%p\n",&p);
p = malloc(sizeof(int));
if(p==NULL)
{
printf("failed\n");
exit(1);
}
printf("%p\n",p);
*p = 4;
printf("%d\n",*p);
return 0;
}
I need to implement a simple dynamic array of pointers to a typedef'ed pointer.
Using realloc each time it's requested by the user, the array size will grow by sizeof(pointer).
So what I have is this:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
typedef void* node;
void printmem(node* a, int c) {
int i;
for (i = 0; i < c; ++i)
{
printf("%d\t\t%p\n", i, a[i]);
}
}
int main(void) {
node* nodes = NULL;
int i = 0, count = 20;
for (i = 0; i < count; ++i)
{
nodes = realloc(nodes, sizeof(node));
}
printf("Done reallocating\n");
printmem(nodes, i);
// free(a);
return 0;
}
This gives the following output:
Done reallocating
0 (nil)
1 (nil)
2 (nil)
3 0x20fe1
4 (nil)
5 (nil)
6 (nil)
7 (nil)
8 (nil)
9 (nil)
10 (nil)
11 (nil)
12 (nil)
13 (nil)
14 (nil)
15 (nil)
16 (nil)
17 (nil)
18 (nil)
19 (nil)
I am concerned about the 3rd element, and its content.
That's why I am asking if I should set to 0 the memory after a new realloc.
Edit:
So, as pointed to the standard of C, by H2CO3, the new call to realloc, is:
nodes = realloc(nodes, (i+1)*sizeof(node));
And after that for initiallization, I did this:
nodes[i] = NULL
which also worked just fine.
Edit2:
I have this now:
int main(void) {
node* nodes = NULL;
int i = 0, count = 20;
for (i = 0; i < count; ++i)
{
nodes = realloc(nodes, (i+1)*sizeof(node));
nodes[i] = NULL;
if (i == 1) {
nodes[i] = &count;
}
}
printf("Done reallocating\n");
printmem(nodes, i);
printf("\t*nodes[1] == %d\n", *(int*)nodes[1]);
printf("\tAddress of count is %p\n", &count);
// free(a);
return 0;
}
Well, it all depends. Do you require that the memory be initialized to 0? If not, then no, you don't need to do anything. Just as is the case with malloc, realloc doesn't perform any initialization. Any memory past the memory that was present in the original block is left uninitialized.
Going by the definition of realloc()
realloc(void *p, size_t size) changes the size of the object pointed
to by p to size. The contents will be unchanged up to the minimum of the old and new sizes. If the new size is larger, the new space is
uninitialized. (from Kernighan and Ritchie)
You may have to initialize the new space. You can do that when it is decided what kind of data the address pointed to by the void* will hold.
Be aware that the null-pointer does not have to be equal to a literal 0 in C. It is merely guaranteed to not be equal to any valid pointer.
Furthermore, null-pointers are technically allowed to be different for different pointer types (e.g. function-pointers vs. char-pointers).
Therefore, simply initialising the memory to zero could invoke undefined behaviour.
So initiallizing to NULL, would be correct! That's what I've done! – Chris
No, what you would have to do is cast the null like this: (void*)NULL, and write this to the memory location. But you never actually write to the memory you malloc (via passing NULL to realloc). You're basically just reading uninitialised memory (which is undefined behaviour) in your printf.
I apologize by advance if my question seems absolutely trivial, but I don't understand why if I run
int main(){
int *count = 0;
printf("%d",*count);
}
I have no input (using Xcode) and an error:
Thread 1 : EXC_BAD_ACCESS(code=1, address = 0x0)
Could someone explain to me what this is?
What happens is dereferencing a null pointer, which is undefined behavior: your count is a pointer, which means that it needs to point to a valid location before you can read from it:
int main(){
int *count = malloc(sizeof(int)); // Give your pointer a valid location
*count = 123; // This is valid now
printf("%d", *count); // prints 123
free(count); // Don't forget to free allocated memory
}
You have declared count as a pointer to an integer value not as an integer value and you have initialized the pointer to be NULL (memory address 0).
You would want to do the following...
int main()
{
int buffer = 0;
int* count = &buffer;
printf( "var %d = %d\n", buffer, *count );
}
I read tons of tutos and snippets, but I still don't understand why I get a segfault with this:
int fun(char **p) {
int i;
*p = malloc(2);
*p[0]=10;
*p[1]=20; // segfault NULL pointer
printf("fun()/n");
for (i=0; i<2; i++)
printf("%d ",*p[i]);
}
int main(int argc, const char *argv[])
{
char* buffer;
int i;
fun(&buffer);
printf("main()\n");
for (i=0; i<2; i++)
printf("%d ",buffer[i]);
return 0;
}
In gdb, it gives:
Program received signal EXC_BAD_ACCESS, Could not access memory.
Reason: KERN_INVALID_ADDRESS at address: 0x0000000000000000
0x0000000100000dea in fun (p=0x7fff5fbffab0) at test.c:10
10 *p[1]=20;
(gdb) p *p[0]
$1 = 10 '\n'
(gdb) p *p[1]
Cannot access memory at address 0x0
(gdb)
I have seen a lot of similar snippets, but there is surely something I am deeply misunderstanding.
You mean (*p)[1]. What you said is *(p[1]).
try returning the address of the same data type of the variable at the LHS.
malloc() by default returns a void value.
p = (char) malloc(2);
this way compiler knows how many bytes it has to move the pointer to fetch new variable.
I have a small piece of code. I compiled it with -lmcheck as I am trying to debug a code where I have the same similar error.
I get this error when I run this code:
memory clobbered before allocated block
Can someone explain the reason why free(ptr) will throw me this error?
How else can I free the pointer?
Thanks.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#define LEN 5
int main(int argc, char *argv[]){
char *ptr = NULL;
ptr = (char *) malloc(LEN+1);// +1 for string
strcpy(ptr, "hello");
int i = 0;
for(i = 0; i<LEN; i++)
{
printf("ptr[%d] = %c\n", i, ptr[i]);
ptr++;
}
free(ptr);
return 0;
}
You are incrementing ptr, therefore changing the address that it points to. You can't do that.
In your case, have a separate pointer, let's say char * p = ptr and do your operations with p leaving ptr intact so you can free(ptr) later.
EDIT Taking a second look at your code, I found that you are doing ptr++ when you shouldn't. You are accessing the characters in the array like ptr[i], if you mess with the ptr pointer, you are changing the base address and accessing the characters with ptr[i] can lead (and will lead) to unexpected results.
If you simply remove that line (ptr++) your code will magically work.
If you want to explore the pointer concept and try another solution, your code could look something like this:
int main(int argc, char *argv[]){
char *ptr = NULL;
char * p;
ptr = (char *) malloc(LEN+1);// +1 for string (please check for NULL)
p = ptr;
strcpy(ptr, "hello");
int i = 0;
while (*p) // note how I changed it to a while loop, C strings are NULL terminated, so this will break once we get to the end of the string. What we gain is that this will work for ANY string size.
{
printf("ptr[%d] = %c\n", i++, *p); // here i dereference the pointer, accessing its individual char
p++;
}
free(ptr);
return 0;
}
Because ptr no longer points to the base of the memory you allocated.
Also, after you increment ptr, the expression ptr[i] does not return what you might expect; and that is why the output starts with "hlo".
Find the answer in comments.
When you allocate some memory, typically, the memory management framework keep tracks of it by adding some more info (you can say Header and Footer) to the allocated memory area. When you free this memory, the same info is matched so as to detect any unwanted/invalid memory access.
int main(int argc, char *argv[]){
char *ptr = NULL;
char* temp = NULL; // Have a temp pointer.
ptr = (char *) malloc(LEN+1);// +1 for string
strcpy(ptr, "hello");
temp = ptr; // manipulate temp pointer instead of ptr itself
int i = 0;
for(i = 0; i<LEN; i++)
{
printf("ptr[%d] = %c\n", i, temp[i]);
temp++; // Why you are incrementing this? Just to print, there is no need of this.
}
free(ptr);
return 0;
}