I'm working with Visual Studio C.
I found that the programs report errors in a strange way when I write outside the range of an allocated vector.
This first program:
#include <stdio.h>
#include <stdlib.h>
int main() {
int* qwe = (int*)calloc(100, sizeof(int));
for (int j = 0; j < 210; j++) qwe[j] = 1; // Wrong range!
printf("Hi!");
for (int k=0;k<1000;k++) \\ just to spend time!
for (int j = 0; j < 100000; j++)
sin(cos(j));
}
simply stops before "Hi!". This one:
#include <stdio.h>
#include <stdlib.h>
int main() {
int* qwe = (int*)calloc(100, sizeof(int));
int* asd = (int*)calloc(100, sizeof(int));
for (int j = 0; j < 210; j++) qwe[j] = 1;
printf("Hi!");
for (int k=0;k<1000;k++)
for (int j = 0; j < 100000; j++)
sin(cos(j));
}
ends without reporting any problem, although the difference is just that I allocated an extra array. And finally this:
#include <stdio.h>
#include <stdlib.h>
int main() {
int* qwe = (int*)calloc(100, sizeof(int));
int* asd = (int*)calloc(100, sizeof(int));
for (int j = 0; j < 210; j++) qwe[j] = 1;
printf("Hi!");
for (int k=0;k<1000;k++)
for (int j = 0; j < 100000; j++)
sin(cos(j));
free(qwe);
free(asd);
}
runs but, at the end (after the useless cycles), it gives me this message:
Of course, I know how to avoid the problem: just, pay attention to the index range. But my question is: what is exactly the meaning of the error message? What is the "normal block"? Why "after" and not "before"? What is exactly the displayed address? Why the message is issued only at the "free" command and not when the "heap corruption" takes place?
_NORMAL_BLOCK tells you what kind of allocation it was, there are also _CRT_BLOCK (internal to the library), _CLIENT_BLOCK (also allocated by user code but with some special handling available), and _FREE_BLOCK.
It's "after" and not "before" due to the order that corruption is check for. Since overruns are more likely than under that is checked for first.
The reason it waits until free is called is simply because it only checks during allocation and de-allocation calls. It would make programs run enormously slower if there were a system in place that checked every write to make sure it is in bounds.
Related
I need to clear memory of 5D object, so first I need to define it with memory allocation.
My previous object definition was:
double I_object[N_GROUPS][NN][NN][NN][NN]={0};
I replaced it by code below and c file compiles but c program crashes :(
I_object=(double *****) malloc(sizeof(double *****)*N_GROUPS);
for(i = 0; i < N_GROUPS; i++){
I_object[i]=(double ****) malloc(sizeof(double****)*NN);
for(j = 0; j < NN; j++){
I_object[i][j]=(double ***) malloc(sizeof(double***)*NN);
for(k = 0; k < NN; k++){
I_object[i][j][k]=(double **) malloc(sizeof(double**)*NN);
for(l = 0; l < NN; l++){
I_object[i][j][k][l]=(double *) malloc(sizeof(double*)*NN);
}
}
}
}
Please let me know if this 5D object definition is wrong or where I can find how to define 5D object using malloc.
You forgot to declare the type of I_object. Also, you need to declare i, j, k and l. Also, I wouldn't cast the result of malloc in C. Furthermore, the indirection levels are wrong in your sizeof() calls, which causes a problem in the last one, where there might be a difference between the sizes of a double and a double*.
With those changes, it looks like this:
#define N_GROUPS 3
#define NN 3
int main() {
double *****I_object = malloc(sizeof(double ****)*N_GROUPS);
for (size_t i = 0; i < N_GROUPS; i++) {
I_object[i] = malloc(sizeof(double***)*NN);
for (size_t j = 0; j < NN; j++) {
I_object[i][j] = malloc(sizeof(double**)*NN);
for (size_t k = 0; k < NN; k++) {
I_object[i][j][k] = malloc(sizeof(double*)*NN);
for (size_t l = 0; l < NN; l++) {
I_object[i][j][k][l] = malloc(sizeof(double)*NN);
}
}
}
}
}
Also, for future questions, I would recommend posting a Minimal, Complete, and Verifiable example. This way, people are much more willing (and capable) to help. For instance, I had to make assumptions about N_GROUPS and NN. Even with low values such as 100 for NN, the memory consumption would already be so high that it will likely cause problems, but without a MCVE, it's hard to tell.
Instead of having array of some pointer to other arrays of some pointers to other arrays of ....
simply use a pointer to array[nn][nn][nn][nn] of doubles.
Something like:
#define NN 2
#define N_GROUPS 4
int main(int argc, char* argv[])
{
double (*I_object)[NN][NN][NN][NN]; // Define pointer
I_object = calloc(N_GROUPS, sizeof * I_object); // Allocate and zero-init memory
I_object[3][1][1][1][1] = 42; // Use as 5D matrix
printf("%f\n", I_object[3][1][1][1][1]);
free(I_object); // Free memory
return 0;
}
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <stdlib.h>
#define MAX_STRING_SIZE 20
int main() {
/* Enter your code here. Read input from STDIN. Print output to STDOUT */
int N, Q;
int i, j, k, l, m, x;
char **str;
scanf("%d\n", &N);
str = (char **)malloc(sizeof(char *) * N);
for(i = 0; i < N; i++){
str[i] = malloc(MAX_STRING_SIZE * sizeof(char));
scanf("%s",str[i]);
}
printf("%d\n",N);
for(j = 0; j < N; j++){
printf("%s",str[j]);
printf("\n");
}
scanf("%d",&Q);
printf("%d\n",Q);
char **qry_str;
qry_str = (char **)malloc(sizeof(char *) * Q);
for(l = 0; l < Q; l++){
qry_str = malloc(MAX_STRING_SIZE * sizeof(char));
scanf("%s",qry_str[l]);
}
for(m = 0; m < N; m++){
printf("%s",qry_str[m]);
printf("\n");
}
for(k = 0; k < N; k++)
free(str[k]);
free(str);
for(x = 0; x < N; x++)
free(qry_str[x]);
free(qry_str);
return 0;
}
I am new to programming, and I am trying to allocate memory for two 2d strings using malloc function, but when I try to input data for the second string qry_str, (null) appears on the screen, and the program exits.
My question is:
How do we dynamically allocate memory for 2D arrays in C multiple times?
Do I need to free the memory first before using it again? (Though when I try to do that it causes segmentation fault error.)
Is this the problem due to my compiler? (I am using gcc.)
In your second case, you're overwriting qry_str inside the loop, which is not what is intended. You most probably want
for(l = 0; l < Q; l++){
qry_str[l] = malloc(MAX_STRING_SIZE * sizeof(char));
scanf("%s",qry_str[l]);
}
That said, a few suggestion:
You don't need four separate counters i, j, l, m. The first clause of for statement re-assigns the counter to 0 anyway, even if you reuse only one.
sizeof(char) is gurantted to be 1 in C. Instead, you should consider writing the statements like
qry_str[l] = malloc(MAX_STRING_SIZE * sizeof *qry_str));
to make them more robust.
Always check for the return values for scanf() family to ensure success.
I have a problem with exercise 5-13 of K&R, the goal of the exercise is to make a function tail that does the same as the *nix command, here's my function:
#include <stdio.h>
#include <string.h>
#include "tail.h"
int tail(int n)
{
char *saved_lines[n];
for (int i = 0; i < n; i++)
saved_lines[i] = "\0";
int line_state[n];
for (int j = 0; j < n; j++)
line_state[j] = 0;
int num_lines = 0, i = 0;
char line[MAXLINE];
saved_lines[n - 1] = "\0";
while (get_line(line, MAXLINE) > 0)
{
for (i = 0; i < n - 1; i++)
{
strcpy(saved_lines[i], saved_lines[i + 1]);
line_state[i] = line_state[i + 1];
}
strcpy(saved_lines[n - 1], line);
line_state[n - 1] = 1;
}
printf("last %d lines: \n", n);
for (i = 0; i < n; i++)
if (line_state[i] == 1)
printf("%d: %s\n", i, saved_lines[i]);
}
problem is when I run it I get a Segmentation fault (core dumped) error, and running it through Valgrind shows the error comes from the call to strcpy:
==25284== Process terminating with default action of signal 11 (SIGSEGV): dumping core
==25284== Bad permissions for mapped region at address 0x108E64
...I don't get why, at first strcpy had a problem with the saved_lines[i] pointers being non initialized, fixing that with
for(int i=0;i<n;i++)
saved_lines[i]="\0";
didn't help...any ideas what could cause this ? thanks in advance!
EDIT: initiated --> initialized
I believe that you've got many more problems, but one is certainly here:
int tail(int n)
{
char *saved_lines[n];
for(int i=0;i<n;i++)
saved_lines[i]="\0";
You are declaring an (variable-length) array of pointers. Then you make this pointer point to a fixed string somewhere in your data segment. Then you go and try to modify that memory. No, no.
You need to reserve memory for each of your lines. You could go for something like:
for(int i = 0; i < n; i++)
saved_lines[i] = calloc(MAXLINE, 1);
But from here there's still a lot to do. Plus you will need to free that memory later.
First of all, I know triple and quadruple pointers are bad practice and are ugly, that's not the point of this question, I'm trying to understand how they work. I'm aware using a struct would be much better.
I am trying to write a function that does some memory operations using memmove() and memcpy() on triple and double pointers that are passed-by-reference (or the C version of that). My memmove() works fine, but the memcpy() yields a SIGSEGV. Here's a minimal example
#include<stdlib.h>
#include<stdio.h>
#include<string.h>
#define UNDO_DEPTH 25
void boardSave(int ***board, int game_sz, int ****history) {
// Shift history to the right
memmove(*history + 1, *history, (UNDO_DEPTH - 1) * sizeof(**history));
// Copy board into history
for (int row = 0; row < game_sz; ++row) {
memcpy((*history)[0][row], (*board)[row], game_sz * sizeof((**board)[row]));
}
}
int main(){
// Game
int game_sz = 5;
// Allocate array for the board
int **board = calloc(game_sz, sizeof(int *));
for (int i = 0; i < game_sz; ++i) board[i] = calloc(game_sz, sizeof(int));
// Allocate array for the history
int ***history = calloc(UNDO_DEPTH, sizeof(int **));
for (int i = 0; i < UNDO_DEPTH; ++i) {
history[i] = calloc(game_sz, sizeof(int *));
for (int j = 0; j < game_sz; ++j) {
history[i][j] = calloc(game_sz, sizeof(int));
}
}
board[0][0] = 1;
boardSave(&board, game_sz, &history);
}
The objective of boardSave() here is to copy board onto history[0]. What am I doing wrong? Why is this causing a segmentation fault?
In the main function you make history point to an array of UNDO_DEPTH pointers, each of which points to a board that has its own allocation. Since memmove moves a contiguous memory blocks, you cannot move the content of all those boards with memmove.
However, you could move down the pointers in that history array, leaving the board allocations untouched.
Just doing a single memmove would require you to free memory of the last board shuffled off, and allocate memory for the new board. But you could recycle that memory by moving the last pointer to the start instead.
Now, there is no need to pass the addresses of board and history to the boardSave function. It just makes your code more complicated for no reason. The simpler version would be:
void boardSave(int **board, int game_sz, int ***history)
{
// Save the last board
int ** last_board = history[UNDO_DEPTH - 1];
// Shuffle down all the boards
memmove( &history[1], &history[0], (UNDO_DEPTH - 1) * sizeof history[0] );
// Put the old last board on the front
history[0] = last_board;
// Copy board into front of history
copy_board( game_sz, history[0], board );
}
// Put a prototype for this earlier in the code. I think it makes
// the boardSave function clearer to use a separate function for this
// operation, which you might end up using on its own anyway.
//
void copy_board( int game_sz, int **dest, int **src )
{
for(int row = 0; row < game_sz; ++row)
memcpy(dest[row], src[row], game_sz * sizeof dest[0][0]);
}
Personally I'd prefer to avoid memcpy in the last function and just write a simple loop that is obviously correct. The compiler will optimize it to use memcpy anyway, but without the possibility of making an error in the memcpy parameters:
for(int row = 0; row < game_sz; ++row)
for (int col = 0; col < game_sz; ++col)
dest[row][col] = src[row][col];
Similar comments would apply to the use of memmove actually.
I would also make some use of const in the function signatures, so that a compiler error is generated if I accidentally switched the "dest" and "src" arguments. But I left that out at this stage for simplicitly.
In main the call would now be:
boardSave(board, game_sz, history);
If you reeeeealy want to pass pointers for practice then I would "de-point" them at the start of the function:
void complicated_boardSave(int ***p_board, int game_sz, int ****p_history)
{
int *** history = *p_history;
int ** board = *p_board;
// rest of code the same
I understand you want to challenge pointers.
I wanted provide a solution that utilizes single pointer.
As a matter of fact, you don't need to use a pointer at all.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
const int game_sz = 5;
#define UNDO_DEPTH 25
void boardSave(int *board[game_sz], int game_sz, int *history[UNDO_DEPTH]
[game_sz])
{
int i,j,k;
for( i = 0; i < UNDO_DEPTH - 1; i++)
for( j = 0; j < game_sz; j ++ )
for( k = 0; j < game_sz; j ++ )
history[i+1][j][k] = history[i][j][k];
for( i = 0; i < game_sz - 1; i++)
for( j = 0; j < game_sz; j++ )
history[0][i][j] = board[i][j];
}
int
main(void)
{
int *board[game_sz];
int *history[UNDO_DEPTH][game_sz];
int i, j;
for (i = 0; i < game_sz; ++i)
board[i] = calloc(game_sz, sizeof(int));
board[0][0] = 1;
// Allocate array for the history
for ( i = 0; i < UNDO_DEPTH; ++i)
for ( j = 0; j < game_sz; ++j)
history[i][j] = calloc(game_sz, sizeof(int));
boardSave( board, game_sz, history);
return 0;
}
I have to be losing my mind here. I'm getting a segfault at the line for(i = 0; i < N; i++) {. I've never encountered anything like this. Here's the full code:
#include <stdio.h>
#include <time.h>
#define N 2400
#define M 2000
#define P 500
int main() {
int a[N][N];
int b[N][N];
int c[N][N];
int i, j;
// Initialize matrix A
for(i = 0; i < N; i++) {
for(j = 0; j < M; j++) {
a[i][j] = j-1+2;
}
}
// Initialize matrix B
for(i = 0; i < M; i++) {
for(j = 0; j < P; j++) {
b[i][j] = i-j+1;
}
}
}
First : you have declared a, b and c as [N][N] matrix, but you initialize them as if they were [N][M] and [M][P] matrix. Considering N > M > P, that should not cause a segfault, but the intent is not clear.
Second, if you replace your defines by :
#define N 10
#define M 5
#define P 2
Your program work. This is because local variables a and b are stored on the stack and your stack is limited in size. Consult your compiler and your system documentation to know exactly the limits imposed.
To avoid such problem, allocate your memory using malloc or equivalent function, that allocate memory on the heap, which is less constrained.