I have a fortran code that I am trying to get to work for my research purposes. The fortran code passes an integer variable and an integer size into a C program that will allocate memory. The code consists of a pointer "iarrays" that point to "arrays(1)". I get a segmentation fault with the following message:
Segmentation Fault
The following is the fortran Code:
subroutine initmem
c-----initial memory setup
pointer ( iarrays , arrays(1) )
c-----allocate pointer memory for blocks and set blocks index pointers
lpoint(0,1) = 0
c-----first call to lpoinst computes storage requirements
call lpoinst
c-----Returns kplast = 1138280 which is the No. of bytes for pointered arrays. I have verified lpoinst works correctly
nwdinc = kplast - lpoint(0,1)
Array lpoint after lpoinst function
c-----nbytaddr = 1
call getmem (lpoint(0,1), (nwdinc*nbytaddr))
c-----Note:getmem is a fortran file only used to check if memory is allocated. I have not included the code in this post.
c-----getmem.F calls C program memalloc(lpoint(0,1), (nwdinc*nbytaddr))
c-----memalloc.c code attached below
c-----value of lpoint(0,1) = -1431465968
c-----second call to lpoinst sets pointers with updated lpoint(0,1).
call lpoinst
Array lpoint after lpoint(0,1) was updated
iarrays = lpoint(0,1)
isize = nwdinc / addrinc
do 100 i=1,isize
arrays(i) = zero
100 continue
return
end
Here is the C program memalloc.c:
#include <stdio.h>
#include <fcntl.h>
#include <stdlib.h>
#ifdef _CRAY
int MEMALLOC (nextptr, size)
#else
#ifdef POST_UNDERSCORE
int memalloc_ (nextptr, size)
#else
int memalloc (nextptr, size)
#endif
#endif
int *size;
int *nextptr;
{
void *ptr;
printf("Size Address:%d Size Value: %d \n", size, *size);
printf("nextptr Address:%d nextptr Value: %d \n", nextptr, *nextptr);
printf("ptr before hexa: %p ptr before int: %d \n", (void *) ptr, (int *) ptr );
if (*nextptr == NULL) {
if ((ptr = (void *) malloc (*size)) == NULL) {
return(-1);
}
}
else {
if ((ptr = (void *) realloc (*nextptr, *size)) == NULL) {
return(-1);
}
}
printf("ptr after hexa: %p ptr after int: %d \n", (void *) ptr, (int *) ptr );
*nextptr = (int) ptr;
printf("nextptr Address:%d nextptr Value: %d \n", nextptr, *nextptr);
return (0);
}
Print statements in memalloc.c
The pointer iarrays is set to a negative value. Can the value of that pointer be negative? Why is not able to access the memory for arrays(i)? Can someone help me get through this segmentation fault?
Thank you!
Related
This question already has answers here:
Changing address contained by pointer using function
(5 answers)
Passing pointer to function value not changing [duplicate]
(4 answers)
Closed 1 year ago.
I don't understand the behavior of this program.
By my understanding, pointer in main() should have the original address of the local variable that is, now, destroyed. Because pointer was assigned the valid address at that point.
It should just keep that address. Why is it losing that?
Here's the program
#include <stdio.h>
void fun(int* ptr)
{
int a = 5;
ptr = &a;
printf("address: %p, value: %d\n", &a, a);
// address: 0x7fff1aa00374, value: 5
printf("address: %p, value: %d\n", ptr, *ptr);
// address: 0x7fff1aa00374, value: 5
}
int main(void)
{
int* ptr = NULL;
fun(ptr);
printf("address: %p\n", ptr);
// address: (nil)
printf("address: %p\tvalue: %d\n", ptr, *ptr);
// Segmentation fault (core dumped)
return 0;
}
GCC Version
gcc (Ubuntu 7.5.0-3ubuntu1~18.04) 7.5.0
Here is a modified example:
#include <stdio.h>
void fun(int p)
{
p = 5;
printf("value: %d\n", p);
}
int main(void)
{
int p = 0;
fun(p);
printf("value: %d\n", p);
return 0;
}
If you understand why this modified example prints 5 then 0, then you also understand why your pointer version doesn't work either. Because pointers too are passed by value.
If you don't understand why this prints 5 then 0, then you need to read a beginner-level C book, functions chapter.
For better understanding of what's happening here, renaming the ptr parameter of fun() function to fun_ptr
void fun(int* fun_ptr)
^^^^^^^
When you call fun() function
int* ptr = NULL;
fun(ptr);
the value of argument ptr will be assigned to fun() function parameter fun_ptr. Its similar to this
fun_ptr = ptr;
ptr is NULL, so the fun_ptr will be assigned NULL. Whatever changes you do in fun_ptr inside fun() function will stay within fun() function block because the scope of identifier within the list of parameter declarations in a function definition has block scope which terminate when function returns.
If you want to make changes to a pointer variable in another function, you have to pass the address of that pointer variable to the calling function. In context of your program, it should be
void fun(int** ptr) {
int a = 5;
*ptr = &a;
// *ptr will be the pointer passed as argument i.e. assign anything
// to *ptr means you are making changes to pointer passed as argument
.....
.....
}
int main(void)
{
int* ptr = NULL;
fun(&ptr);
.....
.....
return 0;
}
Even after making these changes your program will have Undefined Behaviour because it is accessing address of local variable outside of its scope. Variable a is a local(automatic) non-static variable and its lifetime is limited to its scope i.e. the block in which it has been declared. Any attempt to access it outside of its lifetime lead to undefined behaviour.
To resolve this, allocate memory to pointer ptr and assign the value of a to it. Or, you can declare a as static variable. The lifetime of a static variable is entire run of the program. You can do:
#include <stdio.h>
#include <stdlib.h>
void fun1 (int** ptr) {
static int a = 5;
*ptr = &a;
printf("fun1(): address: %p, value: %d\n", (void *)&a, a);
printf("fun1(): address: %p, value: %d\n", (void *)*ptr, **ptr);
}
void fun2 (int** ptr) {
int a = 5;
*ptr = malloc (sizeof (int));
if (*ptr == NULL) {
fprintf (stderr, "Failed to allocate memory\n");
exit (EXIT_FAILURE);
}
**ptr = a;
printf("fun2(): address: %p, value: %d\n", (void *)&a, a);
printf("fun2(): address: %p, value: %d\n", (void *)*ptr, **ptr);
}
int main (void) {
int* ptr1 = NULL;
int* ptr2 = NULL;
fun1(&ptr1);
printf("main(): address: %p\n", (void *)ptr1);
printf("main(): address: %p, value: %d\n", (void *)ptr1, *ptr1);
fun2(&ptr2);
printf("main(): address: %p\n", (void *)ptr2);
printf("main(): address: %p, value: %d\n", (void *)ptr2, *ptr2);
// Once done with dynamic allocated memory, release it
free(ptr2);
return 0;
}
This is because you are passing by value, just like passing an integer, char, etc. You cannot change a parameter passed by value. In this case, the value is the address. To actually change the address of ptr would require passing a passing a double pointer (int **ptr), but that would require more changes to your code.
I feel as though this shouldn't be such a hard problem and I've tried everything that I've found on similar questions to no avail, so I thought I'd give it a try to ask myself. My code (simplified) is as follows:
#include <stdio.h>
#include <stdlib.h>
void setArraySize(int** arr) {
int arrSize;
printf("\nEnter array size: ");
scanf("%d", &arrSize);
int* tmp = realloc(*arr, arrSize);
if (tmp == NULL) {
printf("Error");
return;
}
*arr = tmp;
}
void auswahl() {
int* arr = NULL;
setArraySize(&arr);
free(arr);
}
int main() {
auswahl();
return 0;
}
When debugging I noticed that my array only contains the integer -842150451. I am using Microsoft Visual Studios 2019 Community. Additionally, even when trying the most basic and safest functions, I attain the same result. Could the problem then have to do with Visual Studios?
#include <stdio.h>
#include <stdlib.h>
void increase(int** data)
{
int* tmp = realloc(*data, 20);
if (tmp == NULL) {
printf("Error");
return;
}
*data = tmp;
}
int main() {
int* arr = NULL;
increase(&arr);
printf("%d", sizeof(arr));
return 0;
}
Thanks in advance for any help!
I changed your second code a little bit (added printf's), it will help you understand what is happening
#include <stdio.h>
#include <stdlib.h>
void increase(int** data)
{
printf ("in increase|*data|%p|\n", *data);
int* tmp = realloc(*data, 20);
printf ("in increase|*data after realloc|%p|\n", *data);
printf ("in increase|tmp after realloc|%p|\n", tmp);
if (tmp == NULL) {
printf("Error");
return;
}
*data = tmp;
printf ("in increase|*data after assign|%p|\n", *data);
}
int main() {
int* arr = NULL;
printf ("in main|arr|%p|\n", arr);
printf ("in main|arr size|%d|\n", sizeof(arr));
increase(&arr);
printf ("in main|arr after increase|%p|\n", arr);
printf ("in main|arr size after increase|%d|\n", sizeof(arr));
return 0;
}
this will output this :
in main|arr|(nil)|
in main|arr size|8|
in increase|*data|(nil)|
in increase|*data after realloc|(nil)|
in increase|tmp after realloc|0x2441010|
in increase|*data after assign|0x2441010|
in main|arr after increase|0x2441010|
in main|arr size after increase|8|
So basically the size of arr doesn't change because it's not an array, it's a pointer to an int, the size here is 8 because it's a 64bits machine, and memory adresses for 64bits need 8 Bytes to be stored, and this is what sizeof() returns the size in bytes of the type you gave it ( int* arr a pointer to an int )
for the other values you can see that you have effectively allocated memory in the heap at address 0x2441010 so your QUOTE"array"QUOTE (it's not an array), starts at this address and have enough space for 20(BYTES) if you wanted 20 integers you should have used realloc(..., 20* sizeof(int)) because these alloc functions use bytes as their unit.
hope this helps you somehow.
I'm trying to reallocate memory for an pointers vector, originally the vector is:
Album* albuns
Where Album is a struct;
I created a function passing the adress of type albuns and the total number of albuns as arguments:
void AddAlbum (int* n_albuns, Album** albuns);
I wanted to reallocate memory for albuns so it could receive another pointer to album, so i did:
int aux = (*n_albuns) + 1;
albuns = (Album**) realloc (albuns,(sizeof(Album*) * aux));
albuns[*n_albuns] = (Album*) malloc (sizeof(Album));
(*n_albuns)++;
but the function returns me a SegFault in this line:
albuns[*n_albuns] = (Album*) malloc (sizeof(Album));
Any ideias? I'm relatively new to memory allocation
There are several issues with the question code. See impeded comments.
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/* Question code should include a model of the structure. */
typedef struct Album_s
{
int a;
char b;
int *c;
char *d;
struct Album_s *e;
} Album;
/* Question indicates: void AddAlbum (int* n_albuns, Album** albuns);
** However, in order to change the size of the array, the address of the
** array must be supplied. Hence, the change from **albuns to ***albuns.
*/
int AddAlbum(int *n_albuns, Album ***albums)
{
int rCode = EXIT_SUCCESS;
void *newMem = NULL;
/* Attempt to increase the size of the array by one (pointer) element.
** The question code casts (Album**) the value returned by realloc(),
** which is not necessary. It is also important to verify that the call
** to realloc() actually succeeded. The realloc code below is fairly
** customary in order to check for this.
*/
newMem = realloc(*albums, sizeof(Album *) * (*n_albuns + 1));
if(!newMem)
{
rCode=errno;
goto CLEANUP;
}
*albums = newMem;
/* Again, the question code casts (Album*) the value returned by malloc(),
** which is not necessary. Being that the albums parameter is a pointer
** to a pointer to a pointer, the following assignment is correct. Again,
** it is important to verify that the call to malloc() actually succeeded.
*/
(*albums)[*n_albuns] = malloc(sizeof(Album));
if(!(*albums)[*n_albuns])
{
rCode=errno;
goto CLEANUP;
}
(*n_albuns)++;
CLEANUP:
return(rCode);
}
/* Example of how AddAlbum() might be called. */
int main(void)
{
int rCode = EXIT_SUCCESS;
Album **albunArray = NULL;
int albunCnt = 0;
int desiredCnt = 10;
while(albunCnt < desiredCnt)
{
rCode=AddAlbum(&albunCnt, &albunArray);
if(rCode)
{
fprintf(stderr, "AddAlbum() failed. errno: %d \"%s\"\n", rCode, strerror(rCode));
goto CLEANUP;
}
printf("Array element %d of %d added.\n", albunCnt, desiredCnt);
}
CLEANUP:
return(rCode);
}
This question already has answers here:
Getting a stack overflow exception when declaring a large array
(8 answers)
Closed 6 years ago.
Hi i get a weird segmentation fault from this code:
int main(void){
int array1[10000000];
int n = sizeof(array1);
printf("%d \n", n );
return 0;
}
However if i change
int array1[10000000];
to
int array1[1000000]; ( one less zero)
The program works and prints 4000000
I'm running it on Fedora 21(64bits)
Is this because there is a maximum size for array in C? Thank you in advance
int array1[10000000];
is too large for your stack and you overflow your stack whereas
int array1[1000000];
is large, but does not overflow your stack as the array fits in it.
Note that the size of the stack can vary on different systems and can be set to a particular size.
Methods to solve it:
Make the array static.
Make the array global.
Allocate memory on the heap using malloc from stdlib.h:
int *array1;
array1 = malloc(10000000 * sizeof(int));
if(array1 == NULL) /* If `malloc` failed to allocate memory */
{
fputs("Oops! `malloc` failed to allocate memory!\n", stderr);
exit(-1); /* Exit the program with a return value of `-1` ; Requires `stdlib.h` */
}
/* Use the array and after use, free it using */
free(array1);
An additional method to solve it is to increase stack size with setrlimit. Standard size is 8 MB, at least on my Linux.
#include <stdio.h>
#include <errno.h>
#include <sys/resource.h>
static int setstacksize(rlim_t stacksize)
{
struct rlimit rl;
int res;
if ((res = getrlimit(RLIMIT_STACK, &rl)) != 0) {
fprintf(stderr, "getrlimit result = %d, errno = %d\n", res, errno);
return res;
}
if (rl.rlim_cur >= stacksize) return res;
rl.rlim_cur = stacksize;
if ((res = setrlimit(RLIMIT_STACK, &rl)) != 0) {
fprintf(stderr, "setrlimit result = %d, errno = %d\n", res, errno);
}
return res;
}
static int func(void){
int array1[10000000];
int n = sizeof array1;
printf("%d\n", n);
return 0;
}
int main(void){
setstacksize(48 * 1024 * 1024);
func();
return 0;
}
I'm experimenting with writing malloc and free wrappers, and I wonder why does the following code gives error pointer being freed was not allocated, why does not delete() work?
#include <stdio.h>
#include <stdlib.h>
#define log(v) printf(#v " == %d \n", v)
#define new(n, type) _new((n), sizeof(type), __LINE__, __FILE__)
void *_new(int n, size_t size, int line, char *file)
{
int *ptr;
ptr = malloc(n * size);
if (ptr == NULL)
{
printf("new(): Memory allocation error, file \"%s\", line %d. \n", file, line);
exit(EXIT_FAILURE);
}
return ptr;
}
void delete(int *ptr)
{
free(*ptr);
*ptr = NULL;
}
main()
{
int *p;
p = new(1, int);
log(p);
delete(&p);
log(p);
}
Since you,
int *p;
p = new(1, int);
delete(&p);
Then you should
void delete(int** ptr) //two ** here!!
{
free(*ptr);
*ptr = NULL;
}
You're free()ing the thing the pointer is pointing to (*ptr), not the pointer ptr itself.
Missed the & in the delete() call; sorry.
The problem is this line
free(*ptr);
The free function is expecting a pointer value but you're giving it an int instead. Try this
free(ptr);
EDIT
Why the downvotes? The delete function is flat out incorrect with respect to the usage of free and my statements about it are correct. The fact that the specific incorrect usage of delete makes it all kinda work (it's correctness is platform dependent) doesn't make my answer incorrect.