segfault error: struct, pointer, 2D array - c

I am playing around with pointers and structs. This is the program I have been messing with. I am getting a segfault error and I am not sure why. I have looked through it for awhile but can't seem to pinpoint the issue. Can someone explain it to me?
EDIT: in createArray I am getting a segfault at *purp[i][j] = '1';
#include <stdio.h>
#include <stdlib.h>
struct purple_struct{
int x;
int y;
char **purp;
};
void print(int x, int y){
printf("%d %d\n", x, y);
return;
}
void createArray(char*** purp, int x, int y){
int i, j;
for (i = 0; i < x; ++i){
for (j = 0; j < y; ++j){
*purp[i][j] = '1';
}
}
return;
}
int main(){
int i, j;
struct purple_struct dog;
dog.x = 3;
dog.y = 4;
dog.purp = (char **)malloc(dog.x * sizeof(char *));
for (i = 0; i < dog.x; ++i){
dog.purp[i] = (char *)malloc(dog.y * sizeof(char));
}
createArray(&dog.purp, dog.x, dog.y);
for (i = 0; i < dog.x; ++i){
for (j = 0; j < dog.y; ++j){
printf("%c", dog.purp[i][j]);
}
}
print(dog.x, dog.y);
return 0;
}

You need to understand the concept of operator precedence. Just like in mathematics, where an expression like 1 + 2 × 3 means 1 + (2 × 3) and not (1 + 2) × 3, programming languages have rules as to the order in which different operators in an expression are performed.
The rules for C are here: http://en.cppreference.com/w/c/language/operator_precedence
In your case, the problem is that *purp[i][j] actually means *(purp[i][j]), and not (*purp)[i][j] as you were expecting.

void createArray(char*** purp, int x, int y){
*purp[i][j] = '1';
I think they should be
void createArray(char** purp, int x, int y){
purp[i][j] = '1';
And in main
createArray(&dog.purp, dog.x, dog.y);
'&' is not needed here because you're already passing a pointer. '&' is usually used to pass the address of a variable.
Correcting these few things it compiles just fine, not sure about what you want to do.

Related

How to access the attributes of a struct in a 2D array

I have a simple program that makes a 2d array of a struct. I want to know how to manipulate the struct's attributes. This is my attempt; i keep getting Segmentation fault, the problem happens in the fillarr method;
My problem is that i don't quite understand how to manipulate the data once it is in a 2D array. I understand that arrays are pointers, my assumption at first was that i could do something like
arr[h][w]->one = 'b';
Which i now know is obviously wrong because the compiler really doesn't like it.
Now, when i try
arr[h][w].one = 'a'
The compiler doesn't complain about that syntax, but this is where my segmentation fault triggers.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct node {
char one;
char two;
};
typedef struct node node;
node** makeArr(int h, int w) {
printf("Making arr\n");
node** output = (node**)malloc(sizeof(node*) * h);
for (int i = 0; i < h; i++) {
output[i] = (node*)malloc(sizeof(node) * w);
}
return output;
}
void killarr(node **arr, int h, int w) {
printf("Killing arr\n");
for (int i = 0; i < h; i++) {
free(arr[i]);
}
free(arr);
}
void fillarr(node **arr, int h, int w) {
printf("Filling arr\n");
char x = 'a';
for (int i = 0 ; i < h; i++) {
for(int m = 0; m < w; m++){
arr[h][w].one = x++; // <- here exactly
arr[h][w].two = x++; // <- here too
}
}
}
int main(int argc, char *argv[]) {
int h = 10;
int w = 10;
node **arr = makeArr(h, w);
fillarr(arr, h, w);
killarr(arr, h, w);
}
Each time through the inner loop you're accessing arr[h][w]. But since h and w are the array bounds, you're accessing out of bounds, leading to undefined behavior.
You likely meant:
arr[i][m].one = x++;
arr[i][m].two = x++;

Problems with a dictionary implementation in c

So, I've been trying to implement a dictionary using an array(still haven't written DiDelete function, not relevant right now), but two problems emerged, here's the code:
#include <stdio.h>
#include <stdlib.h>
#define MAX 1000
typedef int elementtype;
typedef struct{
int last;
elementtype elements[MAX];
}Dictionary;
void DiMakeNull(Dictionary *A)
{
(*A).last = -1;
}
int DiMember(elementtype x, Dictionary A)
{
int f,m,l;
f = 0;
l = A.last;
m = (f+l)/2;
while(f <= l )
{
if( A.elements[m] == x) return 1;
else if( A.elements[m] < x) f = m+1;
else l = m-1;
m = (f+l)/2;
}
return 0;
}
void DiInsert(elementtype x, Dictionary *A)
{
int i = 0,j;
elementtype temp;
while( ((*A).elements[i] < x) && ((*A).last >= i) )
{
i++;
}
for(j = i ; j <= (*A).last; j++)
{
(*A).elements[j+1] = (*A).elements[j];
}
(*A).elements[i] = x;
(*A).last++;
}
int DiEmpty(Dictionary A)
{
if(A.last == -1) return 1;
return 0;
}
void DiPrint(Dictionary A)
{
int i;
printf("Dict:\n");
for(i = 0; i <= A.last; i++)
printf("%d\n",A.elements[i]);
printf("End!");
}
Question 1: why does DiPrint not work? After giving a Dictionary with confirmed numbers in its' array of elements it prints out random numbers. It seems fairly simple, I don't understand what I've gotten wrong there!
Question 2: Why is it, that when a function is e.g.
void function(Dictionary *A)
can't I use the notation A->last, but insted I have to use (*A).last
Thanks in advance!
EDIT: main program looks like this:
#include <stdio.h>
#include <stdlib.h>
#include "atp_dictionary_pomocu_liste.c"
int main()
{
Dictionary A;
DiMakeNull(&A);
DiInsert(4,&A);
DiInsert(3,&A);
DiInsert(32,&A);
DiPrint(A);
return 0;
}
Well I will tell you how I debugged. I like my compiler so I compiled the code.
error: could not convert '& A' from 'Dictionary*' to 'Dictionary'
DiPrint(&A);
^
It said to me that I have type mismatch in DiPrint().
Then three changes and it worked.
void DiPrint(Dictionary* A)
{
int i;
printf("Dict:\n");
for(i = 0; i <= (*A).last; i++)
printf("%d\n",(*A).elements[i]);
printf("End!");
}
And also in answer to your question why do we need to derefence it before using? Because we passed the address of the structure. Unless we dereference it , we won't get the struct instance.
From the comment I again had to rollback the code, we need to pass the structure instance directly and so we did
DiPrint(A);
and
void DiPrint(Dictionary A)
{
int i;
printf("Dict:\n");
for(i = 0; i <= A.last; i++)
printf("%d\n",A.elements[i]);
printf("End!");
}
And this would work without those unary *'s because we are working directly on the structure instance.
Isn't A->last and (*A).last the same thing?
Yes they are. That's why when you call it DiPrint(&A) this function would also work.
void DiPrint(Dictionary* A)
{
int i;
printf("Dict:\n");
for(i = 0; i <= A->last; i++)
printf("%d\n",A->elements[i]);
printf("End!");
}
You have an error in your code; in DiPrint(Dictionary A), your function expects type Dictionary but not type Dictionary *, you need to modify this calling function part in your code, so it would be:
DiPrint(A);
Not
DiPrint(&A);
Or another solution is modifying your function to accept a pointer instead, so it would be:
void DiPrint(Dictionary* A)
{
int i;
printf("Dict:\n");
for(i = 0; i <= (*A).last; i++)
printf("%d\n",(*A).elements[i]);
printf("End!");
}

Segmentation Fault During The lsearch in C

#include<stdio.h>
#include<string.h>
#include<stdlib.h>
void* lsearch(int* key,int* base,int count,int elemSize){
int i = 0;
for(i = 0; i < count; i++){
void* elemAddr = (base + (i * elemSize));
if(memcmp(key,elemAddr,elemSize) == 0){
return elemAddr;
}
}
return NULL;
}
int main(){
int a[] = {10,20,30,40,50,60};
int key = a[2];
printf("\n sizeof(a) : %d \n",sizeof(a));
int size = sizeof(a)/sizeof(a[0]);
printf("\n size : %d \n",size);
int* search = lsearch(&key,a,size,sizeof(int));
printf("\n search : %d \n",*search);
return 0;
}
Getting a segmentation fault, dunno why the for loop is looping till the count and returns a NULL, since the key 30 is present in the array a[].
This doesn't do what you think it's doing:
void* elemAddr = (base + (i * elemSize));
The way pointer arithmetic works, adding a value to a pointer actually adds that value times the base datatype size to the pointer. You don't have to do it yourself. So this will do what you want:
void* elemAddr = base + i;
Actually, there's really no need to use memcmp here. You have an array of int and an int value to compare against, so just do that directly:
for(i = 0; i < count; i++){
if (*key == base[i]) {
return &base[i];
}
}
void* lsearch(int* key,int* base,int count,int elemSize){
int i = 0;
for(i = 0; i < count; i++){
void* elemAddr = (base + (i * elemSize));
The problem is how you are assigning elemAddr... you're compensating for the size of each element as well as the index, but you're dealing with int * data so standard pointer math already does this compensation for you; you therefore double compensate.
void* elemAddr = (base + i);
is what you want.
Alternatively you could change the type of base to be a void * which would require you to do the compensation you're already doing.

C Allocating array of 500 and more longs

So.. I have something like this. It is supposed to create arrays with 10, 20, 50 100 .. up to 5000 random numbers that then sorts with Insertion Sort and prints out how many comparisions and swaps were done .. However, I am getting a runtime exception when I reach 200 numbers large array .. "Access violation writing location 0x00B60000." .. Sometimes I don't even reach 200 and stop right after 10 numbers. I have literally no idea.
long *arrayIn;
int *swap_count = (int*)malloc(sizeof(int)), *compare_count = (int*)malloc(sizeof(int));
compare_count = 0;
swap_count = 0;
int i, j;
for (j = 10; j <= 1000; j*=10) {
for (i = 1; i <= 5; i++){
if (i == 1 || i == 2 || i == 5) {
int n = i * j;
arrayIn = malloc(sizeof(long)*n);
fill_array(&arrayIn, n);
InsertionSort(&arrayIn, n, &swap_count, &compare_count);
print_array(&arrayIn, n, &swap_count, &compare_count);
compare_count = 0;
swap_count = 0;
free(arrayIn);
}
}
}
EDIT: ok with this free(arrayIn); I get this " Stack cookie instrumentation code detected a stack-based buffer overrun." and I get nowhere. However without it it's "just" "Access violation writing location 0x00780000." but i get up to 200numbers eventually
void fill_array(int *arr, int n) {
int i;
for (i = 0; i < n; i++) {
arr[i] = (RAND_MAX + 1)*rand() + rand();
}
}
void InsertionSort(int *arr, int n, int *swap_count, int *compare_count) {
int i, j, t;
for (j = 0; j < n; j++) {
(*compare_count)++;
t = arr[j];
i = j - 1;
*swap_count = *swap_count + 2;
while (i >= 0 && arr[i]>t) { //tady chybí compare_count inkrementace
*compare_count = *compare_count + 2;
arr[i + 1] = arr[i];
(*swap_count)++;
i--;
(*swap_count)++;
}
arr[i + 1] = t;
(*swap_count)++;
}
}
I am sure your compiler told you what was wrong.
You are passing a long** to a function that expects a int* at the line
fill_array(&arrayIn, n);
function prototype is
void fill_array(int *arr, int n)
Same problem with the other function. From there, anything can happen.
Always, ALWAYS heed the warnings your compiler gives you.
MAJOR EDIT
First - yes, the name of an array is already a pointer.
Second - declare a function prototype at the start of your code; then the compiler will throw you helpful messages which will help you catch these
Third - if you want to pass the address of a simple variable to a function, there is no need for a malloc; just use the address of the variable.
Fourth - the rand() function returns an integer between 0 and RAND_MAX. The code
a[i] = (RAND_MAX + 1) * rand() + rand();
is a roundabout way of getting
a[i] = rand();
since (RAND_MAX + 1) will overflow and give you zero... If you actually wanted to be able to get a "really big" random number, you would have to do the following:
1) make sure a is a long * (with the correct prototypes etc)
2) convert the numbers before adding / multiplying:
a[i] = (RAND_MAX + 1L) * rand() + rand();
might do it - or maybe you need to do some more casting to (long); I can never remember my order of precedence so I usually would do
a[i] = ((long)(RAND_MAX) + 1L) * (long)rand() + (long)rand();
to be 100% sure.
Putting these and other lessons together, here is an edited version of your code that compiles and runs (I did have to "invent" a print_array) - I have written comments where the code needed changing to work. The last point above (making long random numbers) was not taken into account in this code yet.
#include <stdio.h>
#include <stdlib.h>
// include prototypes - it helps the compiler flag errors:
void fill_array(int *arr, int n);
void InsertionSort(int *arr, int n, int *swap_count, int *compare_count);
void print_array(int *arr, int n, int *swap_count, int *compare_count);
int main(void) {
// change data type to match function
int *arrayIn;
// instead of mallocing, use a fixed location:
int swap_count, compare_count;
// often a good idea to give your pointers a _p name:
int *swap_count_p = &swap_count;
int *compare_count_p = &compare_count;
// the pointer must not be set to zero: it's the CONTENTs that you set to zero
*compare_count_p = 0;
*swap_count_p = 0;
int i, j;
for (j = 10; j <= 1000; j*=10) {
for (i = 1; i <= 5; i++){
if (i == 1 || i == 2 || i == 5) {
int n = i * j;
arrayIn = malloc(sizeof(long)*n);
fill_array(arrayIn, n);
InsertionSort(arrayIn, n, swap_count_p, compare_count_p);
print_array(arrayIn, n, swap_count_p, compare_count_p);
swap_count = 0;
compare_count = 0;
free(arrayIn);
}
}
}
return 0;
}
void fill_array(int *arr, int n) {
int i;
for (i = 0; i < n; i++) {
// arr[i] = (RAND_MAX + 1)*rand() + rand(); // causes integer overflow
arr[i] = rand();
}
}
void InsertionSort(int *arr, int n, int *swap_count, int *compare_count) {
int i, j, t;
for (j = 0; j < n; j++) {
(*compare_count)++;
t = arr[j];
i = j - 1;
*swap_count = *swap_count + 2;
while (i >= 0 && arr[i]>t) { //tady chybí compare_count inkrementace
*compare_count = *compare_count + 2;
arr[i + 1] = arr[i];
(*swap_count)++;
i--;
(*swap_count)++;
}
arr[i + 1] = t;
(*swap_count)++;
}
}
void print_array(int *a, int n, int* sw, int *cc) {
int ii;
for(ii = 0; ii < n; ii++) {
if(ii%20 == 0) printf("\n");
printf("%d ", a[ii]);
}
printf("\n\nThis took %d swaps and %d comparisons\n\n", *sw, *cc);
}
You are assigning the literal value 0 to some pointers. You are also mixing "pointers" with "address-of-pointers"; &swap_count gives the address of the pointer, not the address of its value.
First off, no need to malloc here:
int *swap_count = (int*)malloc(sizeof(int)) ..
Just make an integer:
int swap_coint;
Then you don't need to do
swap_coint = 0;
to this pointer (which causes your errors). Doing so on a regular int variable is, of course, just fine.
(With the above fixed, &swap_count ought to work, so don't change that as well.)
As I told in the comments, you are passing the addresses of pointers, which point to an actual value.
With the ampersand prefix (&) you are passing the address of something.
You only use this when you pass a primitive type.
E.g. filling the array by passing an int. But you are passing pointers, so no need to use ampersand.
What's actually happening is that you are looking in the address space of the pointer, not the actual value the pointer points to in the end. This causes various memory conflicts.
Remove all & where you are inputting pointers these lines:
fill_array(&arrayIn, n);
InsertionSort(&arrayIn, n, &swap_count, &compare_count);
print_array(&arrayIn, n, &swap_count, &compare_count);
So it becomes:
fill_array(arrayIn, n);
InsertionSort(arrayIn, n, swap_count, compare_count);
print_array(arrayIn, n, swap_count, compare_count);
I also note that you alloc memory for primitive types, which could be done way simpler:
int compare_count = 0;
int swap_count = 0;
But if you choose to use the last block of code, DO use &swap_count and &compare_count since you are passing primitive types, not pointers!

complex vector addition using structures in c

I am trying to do complex vector addition and dot product using structures in C for a project. I have my code written, however, while it is compiling without a problem, once i run my program it stops working. I have other parts to the program but this is only the relevant part. I am also trying to do matrix addition and multiplication with complex numbers. I think I can modify the others if I can get these working. Any help at all would be appreciated. Thanks, I appreciate it.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#define PI 3.14159265359
typedef struct complex
{
double re;
double im;
}complex;
typedef struct vect_complex
{
double *re;
double *im;
}vect_complex;
typedef struct mat_complex
{
//int i=0,j=0;
double re[100][100];
double im[100][100];
}mat_complex;
void vector_add(vect_complex a[4], vect_complex b[4], vect_complex c[4])
{
int i;
for(i=0; i<3 ;i++);
{
c->re[i] = a->re[i] + b->re[i];
c->im[i] = a->im[i] + b->im[i];
}
printf("Vector addition = (%f + %f*j)i + (%f +%f*j)j + (%f + %f*j)k\n\n",c- >re[0],c->im[0],c->re[1],c->im[1],c->re[2],c->im[2]);
}
void addmx(mat_complex *a, mat_complex *b, mat_complex *c)
{
int i, j;
for ( i = 0 ; i < '\0' ; i++ )
{
for ( j = 0 ; j < '\0' ; j++ )
{
c->re[i][j] = a->re[i][j] + b->re[i][j];
c->im[i][j] = a->im[i][j] + b->im[i][j];
}
}
printf("***Matrix Addition***\n");
for ( i = 0 ; i < '\0' ; i++ )
{
for ( j = 0 ; j < '\0' ; j++ )
{
printf("(%f + %f*j) ", c->re[i][j],c->im[i][j]);
}
printf("\n");
}
}
int main()
{
vect_complex aaa;
vect_complex bbb;
*aaa.re = 5;
*aaa.im = 4;
*bbb.re = 3;
*bbb.im = 2;
vect_complex ccc;
vector_add(&aaa, &bbb, &ccc);
vector_dot_prod(&aaa, &bbb, &ccc);
return 0;
}
There are a number of issues to deal with here.
1. vect_complex
Perhaps you'd like your vect_complex to hold a fixed number of elements, in which case it should be defined:
typedef struct vect_complex
{
double re[3];
double im[3];
} vect_complex;
Alternatively, you can keep your current definition but you will need to allocate new arrays every time you use the structure:
int main(void)
{
vect_complex vc;
vc.re = (double *) malloc(3 * sizeof(double));
vc.im = (double *) malloc(3 * sizeof(double));
vc.re[0] = 1.0;
vc.im[0] = 2.0;
...
}
2. vector_add
This function should be taking references to vect_complex as inputs, not arrays of complex vectors. This implementation assumes the definition of vect_complex I gave above.
void vector_add(vect_complex * a, vect_complex * b, vect_complex * result)
{
int i;
for (i = 0; i < 3; i++)
{
result->re[i] = a->re[i] + b->re[i];
result->im[i] = a->im[i] + b->im[i];
}
}
3. addmx
I'm not sure what the '\0's are doing here. Change it to
for (i = 0; i < 100; i++)
for (j = 0; j < 100; j++)
{
...
}
At first, your program stops at the line *aaa.re = 5;
int main()
{
vect_complex aaa;
vect_complex bbb;
*aaa.re = 5; //your program stops here.
....
}
The reason is that you defined structure aaa which allocates memory for double pointer re and im , NOT for the double values.
As of now these pointers will point to uninitialized value. when you refer like *aaa.re ie) when you dereference it, you will get segmentation fault.
For example, aaa.re points to 0x17 in my box. when i dereference it, am getting segmentation fault, since it is referring the memory address which is out of program memory area.
To resolve this problem, you should allocate the memory for double and store the address
of it into the pointer re. Then store the double value.
Brain covered Other details perfectly.
Thanks,
nvseenu

Resources