Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 3 months ago.
Improve this question
[valgrind message]
==16958== 1 errors in context 1 of 2:
==16958== Invalid read of size 4
==16958== at 0x109637: arr_del (in /home/students/s/smelov.vp/lab3/lab3)
==16958== by 0x10939D: main (in /home/students/s/smelov.vp/lab3/lab3)
==16958== Address 0x4a19938 is 0 bytes after a block of size 24 alloc'd
==16958== at 0x483E7CF: realloc (in /usr/libexec/valgrind/vgpreload_memcheck-amd64-linux.so)
==16958== by 0x109541: arr_corr (in /home/students/s/smelov.vp/lab3/lab3)
==16958== by 0x109323: main (in /home/students/s/smelov.vp/lab3/lab3)
[functions code]
int main(){
int input=0;
int *arr;
int s;
size_t index;
scanf("%d", &input);
switch(input){
case 2:
scanf("%zu", &index);
arr = arr_corr(arr, index, &s);
arr_output(arr, s);
break;
case 3:
scanf("%zu", &index);
arr = arr_del(arr, index, &s);
arr_output(arr, s);
break;
}
}
int* arr_corr(int *arr, size_t index, int *s){
int n;
(*s) = (*s)+1;
arr = (int*) realloc(arr, (size_t)(*s) * sizeof(int));
for(size_t i = (size_t)((*s)-1); i>=index; i--){
arr[i+1] = arr[i];
}
scanf("%d", &n);
arr[index]= n;
return arr;
}
int* arr_del(int *arr, size_t index, int *s){
for(size_t i=index; i<(size_t)(*s); i++){
arr[i]=arr[i+1];
}
(*s)=(*s)-1;
arr = (int*) realloc (arr, (size_t)(*s) * sizeof(int));
return arr;
}
I just don't understand what this message means and what I did wrong. Pls help me! Everything I know is that there is no problem with main() function and with anything else. The code is located in two files. There is also no problem with linking these files.
==16958== Address 0x4a19938 is 0 bytes after a block of size 24 alloc'd
==16958== at 0x483E7CF: realloc (in /usr/libexec/valgrind/vgpreload_memcheck-amd64-linux.so)
You realloc'd something of size 24 bytes (6 ints).
==16958== Invalid read of size 4
==16958== at 0x109637: arr_del (in /home/students/s/smelov.vp/lab3/lab3)
You tried to read beyond the end of that memory (bytes 24 to 27, or the int array at index 6).
It would be clearer if you compiler your code with debug information (-g).
To fix this you either need to allocate more memory or do something like change your loop control so that you stop sooner and don't read too far.
Related
This question already has answers here:
C - Accessing data AFTER memory has been free()ed?
(2 answers)
Closed 2 years ago.
I'm studying C and I'm seeing something that it's not clear to me.
Here's the code:
#include <stdlib.h>
#include <stdio.h>
int main(void) {
printf("I'm using malloc\n");
int size = 10000000;
int *arr = (int *)malloc(size * sizeof(int));
if (arr == NULL) {
printf("memory could not be allocated\n");
exit(EXIT_FAILURE);
}
for (int i = 0; i < size; i++) {
arr[i] = i;
}
printf("Check the memory of the process\n");
int c;
scanf("%d", &c);
printf("I'm using realloc\n");
int *newArr = realloc(arr, 5 * sizeof(int));
if (newArr == NULL) {
printf("memory could not be allocated\n");
exit(EXIT_FAILURE);
}
int d;
printf("Check the memory of the process\n");
scanf("%d", &d);
for (int i = 0; i < 15; i++) {
printf("%d\n", arr[i]);
}
free(newArr);
}
If I check the process running with top, I can see that the memory of the process shrinks because of the realloc operation, what I wasn't expecting is that the last for loop is actually printing the first 15 numbers from arr. I was expecting an error due to missing elements from 5 to 15.
I'm using malloc
Check the memory of the process
45
I'm using realloc
Check the memory of the process
45
0
1
2
3
4
5
6
7
8
9
10
11
12
13
14
Can you explain to me how this is working?
After the reallocation, you forgot to assign arr with newArr and then you print values form the invalid arr. (UB no 1)
Secondly, even if you assign it (or only change the arr to newArr) in the printf you will access elements outside the array bounds - which is UB no 2
This question already has answers here:
Accessing an array out of bounds gives no error, why?
(18 answers)
Closed 2 years ago.
that's my first question. Sorry if I do something wrong. Thanks for your understanding.
I have a dynamically allocated array,
int *read_array(char *file_path , int *arr){
int max = 0 ,min = 0, i = 0;
FILE *fp = fopen(file_path,"r");
arr= malloc(1 * sizeof(int));
fscanf(fp, "%d,", &arr[i] );
max = arr[i];
min = arr[i];
i++;
arr = realloc(arr , i * sizeof(int));
while(fscanf(fp, "%d,", &arr[i] ) != EOF){
if(max < arr[i]){
max = arr[i];
}
else if(min > arr[i] ){
min = arr[i];
}
i++;
arr = realloc(arr , (i +1) * sizeof(int));
}
printf("%d\n",arr[i + 10]);
free(arr);
}
I tried to print what is at (i+10)th index of my array. It prints "0".
But when I made that printf like printf("%d\n",arr[i + 100000]); I got a seg fault as I expected. But I think I allocated as much memory as "i".
Why arr[i+10] is not giving seg fault ?
Thank you for your time.
This is an array-out-of-bounds logic error, but there's a good chance it's not throwing a segmentation fault because malloc allocated more memory than you were expecting.
The C standard does not require malloc() to return a pointer to exactly the amount of memory you asked for. The parameter you pass to malloc() is treated by the system as the minimum required size for the chunk of memory it returns to you.
It is not uncommon for the system to give you quite a bit more memory than you ask for for alignment and other complicated-operating-system reasons that coders really don't need to know about or understand.
Try compiling and running this program on your system to see proof of what I'm talking about:
#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
#define VALUE 150 //Or whatever you want
int main(){
for(int i=0;i<VALUE;++i){
void *pt=malloc((size_t)i);
printf("Asked for %d bytes, received %zd bytes\n",i,malloc_usable_size(pt));
free(pt);
}
}
This question already has answers here:
Dynamic memory access only works inside function
(1 answer)
How do I modify a pointer that has been passed into a function in C?
(7 answers)
Closed 2 years ago.
I have a question regarding dynamic allocation.
Why do the array values change after using realloc? It works fine if the initial size of the array is greater than the next size (e.g. 10 20) but if the initial size of the array is lesser than the next size (e.g. 20 10), the code gives me garbage values.
The code works properly in local side but when I try it on online compilers, it does not work the way it's supposed to.
Is there anything wrong with my code? Or is it a problem with online compilers? And am I using the realloc function properly?
#include<stdio.h>
#include<stdlib.h>
void print(int *ptr, int size);
void reallocate(int *ptr, int size);
void assign(int *ptr, int size);
int main(void) {
int n;
// Set initial size for array
scanf("%d",&n);
int *arr = (int*) malloc(n * sizeof(int));
// Assign values from 0 to n-1
assign(arr, n);
// Print values assigned
print(arr, n);
printf("\n");
// Set new size for reallocation
scanf("%d",&n);
reallocate(arr, n);
// Assign values again
assign(arr, n);
// Print values
print(arr,n);
return 0;
}
// Prints values of the array
void print(int *ptr, int size) {
for(int i = 0; i < size; i++) printf("%d ",ptr[i]);
}
// Reallocates new size for array
void reallocate(int *ptr, int size) {
ptr = realloc(ptr, size*sizeof(int));
}
// Assigns values from 0 to n-1
void assign(int *ptr, int size) {
for(int i = 0; i < size; i++) ptr[i] = i;
}
I hope for your responses.
This question already has an answer here:
Dynamic memory access only works inside function
(1 answer)
Closed 3 years ago.
I'm experimenting with the dynamic memory allocation of variable sized arrays. The function "ft_ultimate_range" seems to work, however, a problem arises when I try to access and print the values of each array's array. It signals either segmentation fault: 11, when compiled with GCC, or "subscripted value is neither array nor pointer nor vector" with [http://pythontutor.com/c][1]. I understand that this has to do with the use- or abuse of pointers... ehm
// allocate a grid of [n][n] with numbers ranging max-min
int *ft_ultimate_range(int **range, int min, int max)
{
int len, *ptr;
int count = min;
len = max - min;
ptr = range;
// allocate memory **arr
range = malloc(len * sizeof * range);
for(int i = 0; i < len; i++) {
range[i] = malloc(len * sizeof * ptr);
}
// assign values to allocated memory location
for(int i = 0; i < len; i++) {
for(int j = 0; j < len; j++) {
range[i][j] = count++;
}
count = min;
}
// free memory **range
for(int i = 0; i < len; i++) {
free(range[i]);
}
free(range);
return ptr;
}
int main()
{
int n;
n = 6 - 3;
int **ptr, *arr;
arr = ft_ultimate_range(ptr, 3, 6);
// print
for(int i = 0; i < n; i++) {
for(int j = 0; j < n; j++) {
printf("%d", ptr[i][j]);
}
}
return 0;
}
...a little pointer in the right direction would be very much appreciated.
Well, it obvious you are quite lost regarding how to return an allocated grid (pointer-to-pointer-to-int) from ft_ultimate_range() to main().
To begin, you do not need to pass range as a parameter to ft_ultimate_range(). Instead, make the return type int ** and declare int **range within ft_ultimate_range() and then allocate len pointers, and then allocate len integers per-pointer, assign the values and then return range and assign it to arr in main(), e.g.
#include <stdio.h>
#include <stdlib.h>
/* allocate a grid of [n][n] with numbers ranging max-min */
int **ft_ultimate_range (int min, int max)
{
int len = max - min,
**range = NULL,
count = min;
/* allocate len pointers */
range = malloc (len * sizeof * range);
if (!range) { /* validate EVERY allocation */
perror ("malloc-range");
return NULL;
}
/* allocate len int per-pointer */
for (int i = 0; i < len; i++) {
range[i] = malloc (len * sizeof *range[i]);
if (!range[i]) { /* validate alloation */
perror ("malloc-range[i]");
while (i--) /* free previously allocated rows */
free (range[i]); /* free pointers */
free (range);
return NULL;
}
}
/* assign values to allocated memory location */
for(int i = 0; i < len; i++) {
for(int j = 0; j < len; j++) {
range[i][j] = count++;
}
count = min;
}
return range;
}
(note: you MUST VALIDATE EVERY ALLOCATION...)
In main(), you don't need ptr, all you need is the int** pointer you will assign the return from ft_ultimate_range() to, e.g.
int main (void) {
int n = 6 - 3;
int **arr;
arr = ft_ultimate_range (3, 6);
if (!arr) /* validate return */
return 1;
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
printf (" %d", arr[i][j]);
}
putchar ('\n');
free (arr[i]);
}
free (arr);
return 0;
}
(note: similarly, you must validate the return of ft_ultimate_range() before blindly looping through the values (that will not be there if an allocation failed)).
Example Use/Output
$ ./bin/alloc_a_grid
3 4 5
3 4 5
3 4 5
Memory Use/Error Check
In any code you write that dynamically allocates memory, you have 2 responsibilities regarding any block of memory allocated: (1) always preserve a pointer to the starting address for the block of memory so, (2) it can be freed when it is no longer needed.
It is imperative that you use a memory error checking program to insure you do not attempt to access memory or write beyond/outside the bounds of your allocated block, attempt to read or base a conditional jump on an uninitialized value, and finally, to confirm that you free all the memory you have allocated.
For Linux valgrind is the normal choice. There are similar memory checkers for every platform. They are all simple to use, just run your program through it.
$ valgrind ./bin/alloc_a_grid
==29026== Memcheck, a memory error detector
==29026== Copyright (C) 2002-2015, and GNU GPL'd, by Julian Seward et al.
==29026== Using Valgrind-3.12.0 and LibVEX; rerun with -h for copyright info
==29026== Command: ./bin/alloc_a_grid
==29026==
3 4 5
3 4 5
3 4 5
==29026==
==29026== HEAP SUMMARY:
==29026== in use at exit: 0 bytes in 0 blocks
==29026== total heap usage: 4 allocs, 4 frees, 60 bytes allocated
==29026==
==29026== All heap blocks were freed -- no leaks are possible
==29026==
==29026== For counts of detected and suppressed errors, rerun with: -v
==29026== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
Always confirm that you have freed all memory you have allocated and that there are no memory errors.
Look things over and let me know if you have further questions.
Here:
int **ptr, *arr;
arr = ft_ultimate_range(ptr, 3, 6);
ptr is NULL / uninitialised now. You cant allocate of this. malloc must be before call a function ft_ultimate_range. Here: printf("%d", ptr[i][j]); is NULL[i][j].
And you free **ptr in function ft_ultimate_range.
Hope this help.
int **ptr, *arr;
ptr is uninitialised at this point. It's value is indeterminate.
arr = ft_ultimate_range(ptr, 3, 6);
Passing an uninitialised value to a function is always wrong. If you hope the function will initialise it, you are mistaken. Read on pass by value.
ptr = range;
This assignment is wrong. You should have received a compiler warning about it. If you did not, upgrade your compiler ASAP. Never ignore warnings. Toying with a program that compiles with warnings is a waste of time.
for(int i = 0; i < len; i++) {
free(range[i]);
}
free(range);
At this point, every pointer in the program is invalid. Dereferencing them is undefined behaviour.
It isn't at all clear what your program is supposed to return. You are not using the return value anyway.
I suggest changing the signature of your function to this:
int** ft_ultimate_range(int min, int max)
Try to fit whatever you are trying to do in this mold.
This question already has an answer here:
Definitive List of Common Reasons for Segmentation Faults
(1 answer)
Closed 5 years ago.
My program need to have a function in which it finds the largest element of an array. It then returns the position of largest element. However, when finding the largest element, I am only allowed to use pointer arithmetic.
#include <stdio.h>
int *largest(int *array, int size){
int *p1 = array;
int *count, max = *p1;
for(*count = 0; count < p1 + size - 1; p1++){
if (max < *p1){
max = *p1;
count++;
}
}
return count;
}
int main(void){
int *array, size = 10;
printf("enter elements; ");
for(int i = 0; i < size; i++){
scanf("%d ", &array);
array++;
}
printf("\nThe largest element in the array is in element %d", *largest(array, size));
}
However, when I run the program, after enter values for the elements, it gives me:
segmentation fault (core dumped)
Mistakes in the function main:
You didn't allocate memory for the array. You need to add line array = (int*) malloc(sizeof(int) * size);. Without this line you get segmentation fault.
Another mistake is in filling array. Array is pointer already so you don't have to reference it again. Now you are changing pointer, not array values
Potential bug: In loop when you fill array, you increase pointer, so you loose information about beginning of array. You can get it again after loop doing array = array - size;, but it won't work if you break loop earlier. It is better to work with temporary pointer.
Mistakes in the function largest:
You created pointer count, which is not allocated and then in for loop initialization you write value 0 to unknown address. Causes segmentation fault.
In for loop you are trying to read memory from address 0 to address array + size - 2, but you want to read it from beginning of array to the end of array which is from array to array + size - 1.
Returning count makes no sense, but to sum it up, look at the example.
Pointer is just number which is address to memory, so when you don't allocate it or don't assign existing pointer, then it points randomly to memory and OS don't let you access that memory. It can happen that you will read something from random pointer, but new compilers sets initial value to 0. In BSD you can read from address 0, but linux cause segmentation fault (I hope that I didn't switch it). Writing to address 0 causes segmentation fault in both systems.
You should also check in function if you got valid pointer and allocation can fail so you need to check pointer immediatelly after allocation too. To sum this: Never trust pointer, always check it's validity.
Example doesn't check validity of pointers.
#include <stdio.h>
int *largest(int *array, int size){
int *end = array + size; // address behind array
int *max = *array; // address with largest value
for(; array < end; ++array){ // you dont need initialization since the array points to beginning
if (*max < *array){ // compare values, not address
max = array; // save position of pointer with largest value
}
}
return max; // return address with largest value
}
int main(void){
int *array, size = 10;
array = (int*)malloc(sizeof(int) * size); // allocate memory
printf("enter elements; ");
int *tmp = array; // temporary variable to not loose information about beginning of array
for(int i = 0; i < size; i++){
scanf("%d ", tmp); // reference is not needed since tmp is already pointer to value
tmp++;
}
printf("\nThe largest element in the array is in element %d", *largest(array, size));
}