I have a piece of code that calculates coordinates from a user defined size of grid, and prints them to a text file. However when I run the program I get a segmentation fault but only for values of 5 or 7 for the grid, all other values work as intended.
The code is as follows
// Writing OUTPUT 1 to file
// Creating & opening file
FILE *f1 = fopen("coords_output.txt", "w");
if(f1 == NULL)
{
printf("Error in opening file\n");
exit(0);
}
// Writing to file
for(i=0; i < arrayLength; i++)
{
for(j=0; j < arrayLength; j++)
{
fprintf(f1, "\n%d,%d %d", i, j, coordArray[i][j]);
}
}
// Close file
fclose(f1);here
If the whole section under //writing to file is removed the program works, and no matter what I place there the program will fail.
I don't have a great understanding of c, especially when it comes to areas like this, however I have spent a lot of time on trying to fix this problem and cannot seem to come to an answer.
EDIT:
coordArray is defined as
coordArray = malloc(arrayLength * sizeof(int *));
for(i=0; i <= arrayLength; i++)
{
coordArray[i] = malloc(arrayLength * sizeof(int));
}
arrayLength is taken from user input
validInput = validInput && sscanf(argv[1], "%d", &arrayLength);
This code doesn't work (modified from the code you provided):
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
int arrayLength = 5;
int i,j;
int **coordArray;
coordArray = malloc(arrayLength * sizeof(int *));
for(i=0; i <= arrayLength; i++)
{
coordArray[i] = malloc(arrayLength * sizeof(int));
}
for(i=0; i < arrayLength; i++)
{
for(j=0; j < arrayLength; j++)
{
printf("\n%d,%d %d", i, j, coordArray[i][j]);
}
}
return 0;
}
It doesn't work because the first for loop is accessing 1 beyond the end of the array. Even though it may appear to work, the code is broken regardless of the value of arrayLength. The reason it may work for some values is due to how segmentation faults occur, there are lots of resources on the Internet about when and why they occur, here's a random one which seems to explain it well.
This code works (notice the change from <= to < in the first for loop):
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
int arrayLength = 5;
int i,j;
int **coordArray;
coordArray = malloc(arrayLength * sizeof(int *));
for(i=0; i < arrayLength; i++)
{
coordArray[i] = malloc(arrayLength * sizeof(int));
}
for(i=0; i < arrayLength; i++)
{
for(j=0; j < arrayLength; j++)
{
printf("\n%d,%d %d", i, j, coordArray[i][j]);
}
}
return 0;
}
It can be difficult to find bugs like this without using a debugger or an analysis tool like Valgrind. I'd strongly recommend that you take the time to learn how to use tools like that so that you can find the source of these bugs in the future.
Related
I am new to programming and am trying to use two functions for matrix (2D array) operations, where the output of one function is the input for the next.
However, I do not find a way to correctly deliver the values from one function to another. When I print the outputs of the first function in main (), they are correct, but when I input them into the 2nd function and print them, the values make no sense. I have tried it a lot of ways, but it probably fails due to my lack of understanding double pointers.
I am thankful for any hint or advise!
#include <stdio.h>
#include <stdlib.h>
int** td (int r_in, int c_in, int r_p, int c_p, int input[][c_in],int params[][c_p]){
int i, j, k;
int**y_td;
// memory allocation
y_td = (int*)malloc(sizeof(int*)*r_in);
for (i=0; i < r_in; i++){
y_td[i] = (int*)malloc(sizeof(int)*c_p);
}
//
for (i=0; i < r_in; i++){
for (j=0; j < c_p; j++){
y_td[i][j]=0; // Initialization
for (k=0; k < c_in; k++){
y_td[i][j]+= input[i][k]*params[k][j];
}
}
}
return y_td;
}
int** cnv (int r_in, int c_in, int filter, int f_size, int input[][c_in], int params[][f_size][c_in]){
int x,i,j,k,l,m,n;
int min_len = ((r_in < f_size)? r_in:f_size);
int max_len = ((r_in > f_size)? r_in:f_size);
int r_out = max_len - min_len + 1;//rows_out
int kernel;
int** y_cnv;
// Print input to check if it was correctly transmitted to the function
printf("Input CV (should be equal to TD result):\n");
for (i=0;i<r_in;i++){
for (j=0;j<c_in;j++){
printf("%d ", input[i][j]);
}
printf("\n");
}
printf("\n\n");
//memory allocation
y_cnv = (int*)malloc(sizeof(int*)*r_out);
for (i=0; i < r_out; i++){
y_cnv[i] = (int*)malloc(sizeof(int)*filter);
}
//
for (i=0; i < filter; i++){
for (k=0; k < r_out; k++){
y_cnv [k][i]=0; //initialize
}
for (j = 0; j < c_in; j++){
for (n = min_len-1; n < max_len; n++){
x = n-min_len+1;
for (m= 0; m < r_in; m++){
kernel = (((n-m) < min_len && (n-m) >= 0)? params[i][n-m][j]:0);
y_cnv[x][i] += input[m][j]*kernel;
}
}
}
}
return y_cnv;
}
int main() {
// create test arrays
int A [4][2]= {{1,1},{2,2},{3,3},{4,4}};
int B [2][3]= {{1,2,3},{2,3,4}};
int C [2][2][3]= {{{1,1,1},{2,2,2}},{{3,3,3},{4,4,4}}};
int** matrix;
int i, j;
matrix = td(4,2,2,3,A,B);
// print the result of first function, which is input in 2nd function
printf("The TD result is:\n");
for (i=0;i<4;i++){
for (j=0;j<3;j++){
printf("%d ",matrix[i][j]);
}
printf("\n");
}
printf("\n\n");
matrix = cnv(4,3,2,2,matrix,C);
return 0;
}
I expect the matrix printed in main () after the first function td () to be the same as when I read it in the second function cnv () and print it there, but it is not.
take a look at this question. You were hit by the same underlying problem.
Turning
int** cnv (int r_in, int c_in, int filter, int f_size, int input[][c_in], int params[][f_size][c_in])
into
int** cnv (int r_in, int c_in, int filter, int f_size, int** input, int params[][f_size][c_in])
fixes the problem you asked for.
The reason is that you allocate an array of pointers called y_td in your first function. Each of this pointers is a number naming a memory segment where you stored some real numbers. By using int input[][c_in] you tell the computer to interpret these pointers as integer numbers and when you print them you get the addresses in memory instead of the expected values, because then input[x][y] is translated to *((int *)input+x*c_in+y).
Please allow me one more comment: You should follow the comments below the question and care for all compiler warnings: If there is a warning you should treat it as an compiler error unless you exactly know what you are doing, especially in C. Your code contains some possible problem sources like the one above.
I haven't found a similar question for the problem I've ran into. I am only guessing the root of the error, but I don't have enough knowledge to debug it. The code is as follows:
main.c
#include <stdio.h>
#include "adjacency.h"
int main()
{
FILE* textfile;
textfile = fopen("graf.txt", "r");
adjacency_matrix Graph;
create_graph(textfile);
}
adjacency.c
#include "adjacency.h"
#include <stdlib.h>
#include <stdio.h>
adjacency_matrix create_graph(FILE* input)
{
adjacency_matrix graph; int s_node, f_node;
fscanf(input, "%d", &graph.vertices);
int i, j;
graph.matrix = (int**)malloc((graph.vertices + 1) * sizeof(int*));
for (i = 0; i <= graph.vertices; i++)
graph.matrix[i] = (int*)malloc(sizeof(int));
for (i = 0; i <= graph.vertices; i++)
for (j = 0; j <= graph.vertices; j++)
graph.matrix[i][j] = 0;
for (i = 0; i <= graph.vertices; i++)
graph.matrix[i][0] = graph.matrix[0][i] = i;
while (1)
{
fscanf(input, "%d %d", &s_node, &f_node);
if (feof(input))
break;
graph.matrix[s_node][f_node] = 1;
}
return graph;
}
Everything works (I've tested printing the matrix inside the function, before returning the graph struct), but it stops after returning the adjacency_matrix struct called by my function in the main source file.
Visual Studio says
Unhandled exception at 0x77F4A879 (ntdll.dll) in dijkstra.exe: 0xC0000374: A heap has been corrupted (parameters: 0x77F85910).
then points me to exe_common.inl, on line 292.
if (!has_cctor)
_cexit();
I would appreciate some help.
I think you need to allocate more memory for the columns of the matrix:
for (i = 0; i <= graph.vertices; i++)
graph.matrix[i] = (int*)malloc((graph.vertices + 1) * sizeof(int));
I am trying to randomly fill a 2d array with values then multiply them, but for some odd reason when I run my code, on the last iteration, I get a segmentation fault. I have tried decreasing the number I am passing it and everything, but the fault still persists. Here is the code I am trying to execute, any help is much appreciated, thanks.
#include <stdlib.h>
#include <stdio.h>
int main(int argc, char *argv[])
{
FILE *matrixFile;
int n = atoi(argv[1]); // the number of matrices
int i, j; // must declare outside of for loop due to resolve C99 mode error
double arrA[n][n];// = CreateRandomMatrix(n);
double arrB[n][n];
double sumArr[n][n];
matrixFile = fopen("home/acolwell/Documents/CPE631_HW2_Number1/results.txt", "w+");
printf("Usage: %s <size of nxn matrices>\n", argv[1]);
// randomly populate arrA and arrB
for(i = 0; i < n; i++)
{
printf("%d\n", i);
for(j = 0; j < n; j++)
{
printf("%4d", j);
arrA[i][j] = (double)rand()/(double)RAND_MAX;
arrB[i][j] = (double)rand()/(double)RAND_MAX;
}
}
printf("Exiting Matrix randomization");
// multiply the matrices and write them to the file
for(i = 0; i < n; i++)
{
for(j = 0; j < n; j++)
{
sumArr[i][j] = arrA[i][j] * arrB[i][j];
printf("Writing matrix ");
fprintf(matrixFile, "%0.3lf\n", sumArr[i][j]);
}
}
if(matrixFile)
{
fclose(matrixFile);
}
matrixFile = NULL;
return 0;
}
This error is going to come down to writing off the end of your array or failure to open your file. I would suggest running gdb to check out your program when it is running, but from a quick glance I wonder if you don't mean to have
"/home/acolwell/Documents/CPE631_HW2_Number1/results.txt"
as the file to write instead of
"home/acolwell/Documents/CPE631_HW2_Number1/results.txt"
I would suggest checking the result of your fopen call before calling fprintf.
If n is large enough, you'll generate a stack overflow using VLAs. I've verified this experimentally with your code (e.g. use n of 5000).
So, you'll need to use malloc to allocate from heap. But, that would require a bit of a rewrite.
Here's a way to use heap allocation and get the benefit of a VLA [using some slight trickery]:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define C(_arr) (double (*)[(size_t)(n)]) _arr
void
docalc(FILE *fout,int n,double arrA[n][n],double arrB[n][n],double sumArr[n][n])
{
// must declare outside of for loop due to resolve C99 mode error
int i,
j;
// randomly populate arrA and arrB
for (i = 0; i < n; i++) {
printf("%d\n", i);
for (j = 0; j < n; j++) {
printf("%4d", j);
arrA[i][j] = (double) rand() / (double) RAND_MAX;
arrB[i][j] = (double) rand() / (double) RAND_MAX;
}
}
printf("Exiting Matrix randomization");
// multiply the matrices and write them to the file
for (i = 0; i < n; i++) {
for (j = 0; j < n; j++) {
sumArr[i][j] = arrA[i][j] * arrB[i][j];
printf("Writing matrix\n");
fprintf(fout, "%0.3lf\n", sumArr[i][j]);
}
}
}
int
main(int argc, char *argv[])
{
FILE *matrixFile;
int n = atoi(argv[1]); // the number of matrices
printf("Usage: %s <size of nxn matrices>\n", argv[1]);
matrixFile = fopen("/tmp/results.txt", "w+");
if (matrixFile == NULL) {
perror("fopen");
exit(1);
}
double *arrA = malloc(sizeof(double) * n * n);
double *arrB = malloc(sizeof(double) * n * n);
double *sumArr = malloc(sizeof(double) * n * n);
docalc(matrixFile,n,C(arrA),C(arrB),C(sumArr));
if (matrixFile)
fclose(matrixFile);
matrixFile = NULL;
return 0;
}
I just compiled and tested your code. The file name you are giving is incorrect; you need a "/" in front of "home".
Not sure what the requirements are, but write your matrixFile like a matrix: add a new line after each row of the matrix is "multiplied", not after every element:
for(i = 0; i < n; i++) {
for(j = 0; j < n; j++) {
sumArr[i][j] = arrA[i][j] * arrB[i][j];
printf("Writing matrix ");
fprintf(matrixFile, "%0.3lf ", sumArr[i][j]);
}
fprintf(matrixFile, "\n");
}
Also, take Craig Easley's comment seriously. Stack Overflow can happen, even off the premises this website ;) Consider allocating your matrix dynamically on the heap.
I am trying to use a simple program to draw a Mandelbrot Set - the program produces an array of integers which correspond to colors in an image. I am working in Code::Blocks on Windows with gcc/MiniGW. It works great for small array sizes (~500x500). However, when I try and run after setting to 1000x1000, it crashes ("has stopped responding"). The same code compiles and executes successfully for any array size under a linux remote terminal using gcc (CentOS) with no special calling instructions.
I think what I need to do is increase the stack size under Code::Blocks. To this end I have tried "-Wl,--stack,1024" under linker options in Code::Blocks. However I can no longer build -"unrecognized command line option '--stack,1024". Is there something wrong with this call?
I'll put the code here but since it works on Linux as expected I don't think it is the issue.
int cal_pixel(double complex d,double b, int Nmax){
int count = 1;
double complex z = 0;
while (cabs(z) < b && count < Nmax){
z=cpow(z,2)+d;
count=count+1;
}
return count;
}
int main(int argc, char **argv) {
unsigned int color[M][N];
int i;
int j;
double complex d;
double dx;
double dy;
double b = 2;
char delim;
delim = ',';
dx = 2*b/(M-1);
dy = 2*b/(N-1);
FILE *fp;
d=-3+0.1*I;
for (j = 0;j < N; j++){
for (i = 0; i < M; i++){
d=(i*dx-b)+(j*dy-b)*I;
color[i][j]=cal_pixel(d,2,250);
}
}
fp = fopen("color.csv","w+");
for (j = 0; j < N; j++) {
for (i = 0; i < M; i++){
fprintf(fp, "%d", color[i][j]);
fprintf(fp, "%c",delim);
}
fprintf(fp, "\n");
}
fclose(fp);
return 0;
}
#include <stdio.h>
#include <stdlib.h>
#define MAX_ROWS 5
#define MAX_COLS 5
int globalvariable = 100;
void CreateMatrix(int ***Matrix)
{
int **ptr;
char *cp;
int i = 0;
*Matrix = (int**)malloc((sizeof(int*) * MAX_ROWS) + ((MAX_ROWS * MAX_COLS)*sizeof(int)));
ptr = *Matrix;
cp = (char*)((char*)*Matrix + (sizeof(int*) * MAX_ROWS));
for(i =0; i < MAX_ROWS; i++)
{
cp = (char*)(cp + ((sizeof(int) * MAX_COLS) * i));
*ptr = (int*)cp;
ptr++;
}
}
void FillMatrix(int **Matrix)
{
int i = 0, j = 0;
for(i = 0; i < MAX_ROWS; i++)
{
for(j = 0; j < MAX_COLS; j++)
{
globalvariable++;
Matrix[i][j] = globalvariable;
}
}
}
void DisplayMatrix(int **Matrix)
{
int i = 0, j = 0;
for(i = 0; i < MAX_ROWS; i++)
{
printf("\n");
for(j = 0; j < MAX_COLS; j++)
{
printf("%d\t", Matrix[i][j]);
}
}
}
void FreeMatrix(int **Matrix)
{
free(Matrix);
}
int main()
{
int **Matrix1, **Matrix2;
CreateMatrix(&Matrix1);
FillMatrix(Matrix1);
DisplayMatrix(Matrix1);
FreeMatrix(Matrix1);
getchar();
return 0;
}
If the code is executed, I get the following error messages in a dialogbox.
Windows has triggered a breakpoint in sam.exe.
This may be due to a corruption of the heap, which indicates a bug in sam.exe or any of the DLLs it has loaded.
This may also be due to the user pressing F12 while sam.exe has focus.
The output window may have more diagnostic information.
I tried to debug in Visual Studio, when printf("\n"); statement of DisplayMatrix() is executed, same error message is reproduced.
If I press continue, it prints 101 to 125 as expected. In Release Mode, there is no issue !!!.
please share your ideas.
In C it is often simpler and more efficient to allocate a numerical matrix with calloc and use explicit index calculation ... so
int width = somewidth /* put some useful width computation */;
int height = someheight /* put some useful height computation */
int *mat = calloc(width*height, sizeof(int));
if (!mat) { perror ("calloc"); exit (EXIT_FAILURE); };
Then initialize and fill the matrix by computing the offset appropriately, e.g. something like
for (int i=0; i<width; i++)
for (int j=0; j<height; j++)
mat[i*height+j] = i+j;
if the matrix has (as you show) dimensions known at compile time, you could either stack allocate it with
{ int matrix [NUM_COLS][NUM_ROWS];
/* do something with matrix */
}
or heap allocate it. I find more readable to make it a struct like
struct matrix_st { int matfield [NUM_COLS][NUM_ROWS]; };
struct matrix_st *p = malloc(sizeof(struct matrix_st));
if (!p) { perror("malloc"); exit(EXIT_FAILURE); };
then fill it appropriately:
for (int i=0; i<NUM_COLS; i++)
for (int j=0; j<NUM_ROWS, j++)
p->matfield[i][j] = i+j;
Remember that malloc returns an uninitialized memory zone so you need to initialize all of it.
A two-dimensional array is not the same as a pointer-to-pointer. Maybe you meant
int (*mat)[MAX_COLS] = malloc(MAX_ROWS * sizeof(*mat));
instead?
Read this tutorial.
A very good & complete tutorial for pointers, you can go directly to Chapter 9, if you have in depth basic knowledge.