This question already has answers here:
Crash or "segmentation fault" when data is copied/scanned/read to an uninitialized pointer
(5 answers)
Closed 2 years ago.
Background context:
I was doing leetcode twoSum and trying to understand one of the solutions. So, I decided to implement the solutions in the code block and use the debugger.
#include <stdio.h>
#include <stdlib.h>
#define SIZE 50000
int hash(int key);
void insert(int *keys, int *values, int key, int value);
int search(int *keys, int *values, int key);
int* twoSum(int* nums, int numsSize, int target, int* returnSize);
int main()
{
int ar[4]={2,7,11,15};
int *ans;
int *returnSize;
ans=malloc(2*sizeof(int));
ans=twoSum(ar,4,9,returnSize);
printf("d d ",ans[0],ans[1]);
free(ans);
return 0;
}
int hash(int key) {
int r = key % SIZE;
return r < 0 ? r + SIZE : r;
}
void insert(int *keys, int *values, int key, int value) {
int index = hash(key);
while (values[index]) {
index = (index + 1) % SIZE;
}
keys[index] = key;
values[index] = value;
}
int search(int *keys, int *values, int key) {
int index = hash(key);
while (values[index]) {
if (keys[index] == key) {
return values[index];
}
index = (index + 1) % SIZE;
}
return 0;
}
int* twoSum(int* nums, int numsSize, int target, int* returnSize){
*returnSize = 2;
int keys[SIZE]; //new array
int values[SIZE] = {0}; //new array
for (int i = 0; i < numsSize; i++) {
int complements = target - nums[i];
// check for complements in the hash table
int value = search(keys, values, complements);
if (value) {
//return an array
int *indices = (int *) malloc(sizeof(int) * 2);
indices[0] = value - 1;
indices[1] = i;
return indices;
}
//if not insert the current values
insert(keys, values, nums[i], i +1);
}
return NULL;
}
When I use the debugger, the error SEGMENTATION fault appears at line *returnSize=2?
What is the problem?
I was trying to understand why i+1 in insert(keys, values, nums[i], i +1) instead of i?
You need to initialize returnSize before you can dereference it. You've got UB because you dereference a pointer that is not initialized. But I suspect what you really wanted was to have returnSize as an output parameter, which would look like this:
int main()
{
int ar[4]={2,7,11,15};
int *ans;
int returnSize;
ans=malloc(2*sizeof(int));
ans=twoSum(ar,4,9, &returnSize);
printf("d d ",ans[0],ans[1]);
free(ans);
return 0;
}
Note that returnSize in main() is now of type int (not int*). Its address is passed to the function twoSum. The difference is that the pointer passed to the function points to an existing variable.
Related
I was doing a question about finding an element in an array using function pointer concept. But I am facing some issues regarding this.
Here is my code.
#include <stdio.h>
#include <stdbool.h>
bool compare( const void* a, const void* b)
{
return (*(int*)a == *(int*)b);
}
int search(const void * arr, int arr_size, int ele_size, void* x, bool compare(const void*, const void*))
{
char* ptr = *(char**)arr;
int i;
for (i = 0; i < arr_size; i++)
{
if (compare(ptr + i * ele_size, x))
{
return i;
}
}
return -1;
}
int main()
{
int arr[] = { 2, 5, 7, 90, 70 };
int n = sizeof(arr) / sizeof(arr[0]);
int x = 7;
printf("Returned index is %d ", search(arr, n, sizeof(int), &x, compare));
return 0;
}
The code is compile fine but not giving any output?
What is wrong with this code?
No need to de-reference arr, just alter its type to do the pointer math.
// char *ptr = *(char**) arr;
const char *ptr = arr;
Minor: Best practice to use const here.
This question already has answers here:
How do I modify a pointer that has been passed into a function in C?
(7 answers)
Closed 3 years ago.
I'm trying to understand why this doesn't work as I want it to.
I'm trying to malloc an integer pointer inside a function and return to the main function with the values intact. I assumed you can do this as the integer pointer is just an address, same with the size variable. So I thought the newPtr will have the contents of the values but it does not. Why is this?
I tried to see how to make this work but only idea I've come up with is to make function parameter type int * * arr.
#include <stdio.h>
#include <stdbool.h>
#include <stdlib.h>
bool readData(int * arr, int * size);
int main() {
int i;
int countSize = 10;
int * newPtr;
bool rtv = true;
rtv = readData(newPtr, &countSize);
if (rtv == false) {
printf("read data failed\n");
return -1;
}
for (i = 0; i < countSize/2; i++) {
printf("%d\t", newPtr[i]);
}
printf("\n");
printf("new size: %d\n", countSize);
free(newPtr);
return 0;
}
bool readData(int * arr, int * size) {
int i;
arr = malloc(sizeof(int*) * *size);
if (arr == NULL) {
printf("malloc error\n");
return false;
}
for (i = 0; i < *size; i++) {
arr[i] = i * i;
}
for (i = 0; i < *size; i++) {
printf("[%d] = %d\n", i, (arr)[i]);
}
*size = *size * 2;
return true;
}
The trouble is you're using a regular pointer:
bool readData(int * arr, int * size)
So when you assign in there like this:
arr = malloc(sizeof(int*) * *size);
You're changing the local value of the pointer. To manipulate the root value, you need to do this:
bool readData(int** arr, int * size)
Where then you do:
*arr = malloc(sizeof(int*) * *size);
That's kind of messy though. Instead just shift that to a return value:
int* readData(int * size) {
int* arr = malloc(...);
// ...
return arr;
}
And capture that at the top:
int* rtv = readData(&countSize);
Where you can always return NULL if something went horribly wrong.
I had a question about circular array population essentially my code prints out random data into a txt file call car_data. I was wondering if someone could help me understand why under the add_it and write_it functions i am using the index%size? under ptr[<argument>]. I also had a question about the add_it part where the function goes to ptr[index++] so the index will increment in the main under the for loop so the array can be populated?
Thanks guys! I'm just trying to learn and will appreciate any clarity
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
typedef struct sdata{
int brake_fluid_pressure;
int electrical_power;
int driver_brake_pressure;
int pressure;
float time;
} Data_slice;
Data_slice make(int f, int p, int d, int e, float t){
Data_slice piece; //members for each type of data
piece.brake_fluid_pressure = f;
piece.pressure = p;
piece.driver_brake_pressure = d;
piece.electrical_power = e;
piece.time = t;
return piece;
}
int rand_gen(int min, int max);
int add_it(Data_slice * ptr, int size, int index);
void write_it(char *car_data, Data_slice ptr[], int size, int index);
int main()
{
srand(time(NULL));
Data_slice data[100];
int i;
int num = 0;
for (i=0; i<1177; i++){
num = add_it(data, 100, num);
}
write_it("car_data.txt", data, 100, num);
return(0);
}
int rand_gen(int min, int max){
return (rand() % (max + 1 - min)) + min;
}
int add_it(Data_slice * ptr, int size, int index){
Data_slice temp = make(rand_gen(20,30),
rand_gen(10, 15),
rand_gen(20,40),
rand_gen(10,100),
0);
index = index % size;
ptr[index++] = temp; //THIS PART I DO NOT UNDERSTAND!
return index;
}
void write_it(char *car_data, Data_slice ptr[], int size, int index){
FILE * fout = fopen("car_data.txt", "w");
if(fout == NULL){
printf("Error writing! Program will exit");
exit(0);
}
int i, ind;
float t = 0.1;
for(i=index; i<index+size; i++){
ind = i % size;
ptr[ind].time = t;
fprintf(fout, "%5.1f%20d%20d%20d%20d\n", ptr[ind].time,
ptr[ind].brake_fluid_pressure,
ptr[ind].pressure,
ptr[ind].driver_brake_pressure,
ptr[ind].electrical_power);
t += 0.1;
}
fclose(fout);
}
% is the modulus operator. index % size returns the remainder of dividing index by size. This is used to make the index wrap around to 0 when it goes beyond the size of the array, and that's what makes the array "circular".
ptr[index++] = temp;
assigns temp to ptr[index], and then increments index. This updated value of index is then returned by the function, and main assigns it back to the num variable.
I'm getting various errors and warnings that I don't understand.
error: "subscripted value is neither array nor pointer nor vector" in the top two functions with the arrays
warning: passing argument 1 of ‘SelectionSort’ makes integer from pointer without a cast
int s = SelectionSort(arr, len);
note: expected ‘int’ but argument is of type ‘int *’: void SelectionSort(int arr, int len) {
error: void value not ignored as it ought to be: int s = SelectionSort(arr, len);
It sounds like they're simple fixes but types and values are my weak point! Any pointers? (pun unintended)
int find_maxind(int arr, int len) {
if(len == 1) return 0;
int ind = find_maxind(arr,len-1);
return (arr[ind] > arr[len-1])?ind:len-1;
}
void SelectionSort(int arr, int len) { //this cannot change
if(len <= 1) return;
int max_ind = find_maxind(arr,len);
int temp = arr[max_ind];
arr[max_ind] = arr[len-1];
arr[len-1] = temp;
SelectionSort(arr, len-1);
}
int main(){ //testing the sorting
int arr[] = {1,2,3,4,5,6,7,8,9,11,13,15,17};
int len = 13;
int s = SelectionSort(arr, len);
}
Complete working code.
int find_maxind(int arr[], int len) {
if(len == 1) return 0;
int ind = find_maxind(arr,len-1);
return (arr[ind] > arr[len-1])?ind:len-1;
}
void SelectionSort(int arr[], int len) { //this cannot change
if(len <= 1) return;
int max_ind = find_maxind(arr,len);
int temp = arr[max_ind];
arr[max_ind] = arr[len-1];
arr[len-1] = temp;
SelectionSort(arr, len-1);
}
int main(){ //testing the sorting
int arr[] = {1,2,3,4,5,6,7,8,9,11,13,15,17};
int len = 13;
SelectionSort(arr, len);
}
Basically your program needs some changes:
int find_maxind(int arr, int len) to int find_maxind(int arr[], int len)
void SelectionSort(int arr, int len) to void SelectionSort(int arr[], int len)
Because you're passing arr in SelectionSort(arr, len);
I hope you got the answer.
There are a couple issues here:
int find_maxind(int arr, int len) {
Is taking only one integer instead of your desired array. Change it to something like this:
int find_maxind(int[] arr, int len) {
As for your second error: Your SelectionSort function is defined to have a void return type, meaning it does not return anything. So when you try to assign its return value to s, the compiler moans:
int s = SelectionSort(arr, len);
See, the function doesn't return anything (certainly no int), so assigning its return value to anything is nonsensical.
There are more problems, but these are the ones that your errors mention.
I'd recommend you read up a little more on pointers and arrays in C before you tackle something like this. Also on return types.
Try the code below it is working:
#include<stdio.h>
int find_maxind(int arr[], int len)
{
if(len == 1) return 0;
int ind = find_maxind(arr,len-1);
return (arr[ind] > arr[len-1])?ind:len-1;
}
void SelectionSort(int arr[], int len)
{ //this cannot change
if(len <= 1) return;
int max_ind = find_maxind(arr,len);
int temp = arr[max_ind];
arr[max_ind] = arr[len-1];
arr[len-1] = temp;
SelectionSort(arr, len-1);
}
int main(){ //testing the sorting
int arr[] = {17,2,3,4,5,6,7,8,9,11,13,15,1};
int len = 13;
SelectionSort(arr, len);
for (int i=0;i<len;i++)
{
printf("%d\n",arr[i]);
}
}
You are passing an array and receiving with an int type that will surely create a problem.
You can catch the array with an array type or a pointer type but never with a primary type of variable as you are doing in your code right now.
Your functions are not taking arrays as inputs. You are just passing integers. You should change functions find_maxind and SelectionSort to int find_maxind(int* arr, int len) and void SelectionSort(int* arr, int len)
The function SelectionSort does not return anything. So in the main function, change the call from int s = SelectionSort(arr, len); to SelectionSort(arr, len);
Your array arr is already sorted. I do not see the point in calling selection sort on it. You can change this array.
I am having a trouble while practicing double pointer
The Error is "EXE_BAD_ACCESS" in Xcode
#include <stdio.h>
/* Program to Get Min and Max Value
in Array */
void SaveValue(int **maxPtr, int **minPtr, int arr[])
{
int i;
**maxPtr=arr[0]; // Error Line
**minPtr=arr[0]; // Error Line
for(i=1; i<5; i++)
{
if(arr[i]>**maxPtr)
**maxPtr=arr[i];
else if(arr[i]<**minPtr)
**minPtr=arr[i];
}
}
int main()
{
int arr[5]={4, 5, 7, 2, 6};
int *maxptr;
int *minptr;
SaveValue(&maxptr, &minptr, arr);
printf("%d, %d \n", *maxptr, *minptr);
}
I've thought that *dptr of **dptr = &ptr is *ptr
and **dptr means variable which *ptr pointing.
so I assume that **dptr = arr[0] means save first num of arr by reference at variable which *ptr pointing!
but I experiencing access error now.. I will thank for your help!
void SaveValue(int **maxPtr, int **minPtr, int arr[]); provides pointers to pointers to int so use them as such.
void SaveValue(int **maxPtr, int **minPtr, int arr[])
{
int i;
*maxPtr=arr + 0; /* same as *maxPtr = &arr[0]; */
*minPtr=arr + 0; /* same as *maxPtr = &arr[0]; */
for(i = 1; i < 5; i++)
{
if(arr[i] > **maxPtr)
*maxPtr = arr + i; /* same as *maxPtr = &arr[i]; */
else if(arr[i] < **minPtr)
*minPtr = arr + i; /* same as *minPtr = &arr[i]; */
}
}
Also this interface is a bit dangerous and unflexible; so why not pass the size of the array as well:
void SaveValue(int **maxPtr, int **minPtr, int arr[], ssize_t s)
{
*maxPtr=arr + 0;
*minPtr=arr + 0;
for(--s; s >= 0; --s)
{
if(arr[s] > **maxPtr)
{
*maxPtr = arr + s;
}
else if(arr[i] < **minPtr)
{
*minPtr = arr + s;
}
}
}
Call the fcuntion like this:
SaveValue(&maxptr, &minptr, arr, sizeof arr/sizeof *arr);
As the return value of the function is unused we could utlize it to apply some error inidication to allow the user of the function to write more stable code:
int SaveValue(int ** maxPtr, int ** minPtr, int arr[], ssize_t s)
{
int result = 0;
if ((NULL == arr) || (NULL == maxPtr) || (NULL == minPtr) || (0 > s))
{
result = -1;
errno = EINVAL;
}
else
{
*maxPtr=arr + 0;
*minPtr=arr + 0;
for(--s; s >= 0; --s)
{
if(arr[s] > **maxPtr)
{
*maxPtr = arr + s;
}
else if(arr[i] < **minPtr)
{
*minPtr = arr + s;
}
}
}
return result;
}
Use it like this:
#include <stdio.h>
int SaveValue(int ** maxPtr, int ** minPtr, int arr[], ssize_t s);
int main(void)
{
int arr[5]={4, 5, 7, 2, 6};
int *maxPtr;
int *minPtr;
int result = SaveValue(&maxPtr, &minPtr, arr, sizeof arr/sizeof *arr);
if (-1 == result)
{
perror("SaveValue() failed")
}
else
{
printf("%d, %d \n", *maxPtr, *minPtr);
}
}
The pointer should be pointing to valid memory location before dereferencing it else it will lead to undefined behavior. Below changes will fix your error.
int max;
int min;
int *maxptr = &max;
int *minptr = &min;
There is no need of double pointer here change your function prototype to
void SaveValue(int *maxPtr, int *minPtr, int arr[])
Have
int max;
int min;
in main() and call this API accordingly
SaveValue(&max,&min,arr);
I'll assume your code is purely for pointer learning purposes and not an attempt to implement this operation in a practical situation. So if you want to have maxptr and minptr in main() pointing to the maximum and minimum values in arr[], I think you should change your double pointer assignments from **maxPtr=arr[0] to *maxPtr=&arr[0], so your code would become:
void SaveValue(int **maxPtr, int **minPtr, int arr[])
{
int i;
*maxPtr = &arr[0]; // Error Line
*minPtr = &arr[0]; // Error Line
for (i = 1; i < 5; i++) {
if (arr[i] > **maxPtr)
*maxPtr = &arr[i];
else if (arr[i] < **minPtr)
*minPtr = &arr[i];
}
}
In this case, when you make the assignments, you don't want to dereference the double pointers. Instead, you should assign it with the address of the element you want to show when you dereference them in main().
You don't need to use the double asterisk when initialize the maxPtr and minPtr pointers in the function SaveValue, neither in the for loop body. MaxPtr and minPtr both are double pointers, but is still the memory direction of maxptr in main(). So you only need to dereference them with a single asterisk, to acces the memory direction them points to.
The source correct source code is this:
#include <stdio.h>
/* Correct program to Get Min and Max Value in Array */
void SaveValue(int **maxPtr, int **minPtr, int arr[])
{
int i;
*maxPtr=arr[0];
*minPtr=arr[0];
for(i=1; i<5; i++)
{
if(arr[i]>*maxPtr)
*maxPtr=arr[i];
else if(arr[i]<*minPtr)
*minPtr=arr[i];
}
}
int main(void)
{
int arr[5]={4, 5, 7, 2, 6};
int *maxptr;
int *minptr;
SaveValue(&maxptr, &minptr, arr);
printf("%d, %d \n", maxptr, minptr);
return 0;
}
When I compile it with GCC and execute it, i get the next output:
7, 2.
Remember that depending of the environment (Operating System, version, compiler, standards) that you use the program results may vary.