Reputation: 2022
I am trying to use memcpy
C library function to swap rows of 2D array(array of strings). Source files for this task is below:
main.c
#include <stdlib.h>
#include "main.h"
char *table[NBLOCK] = {
"abcdefghi",
"defghiabc",
"ghiabcdef",
"bcaefdhig",
"efdhigbca",
"higbcaefd",
"cabfdeigh",
"fdeighcab",
"ighcabfde",
};
int main() {
swap_rows(table, 0, 2);
return 0;
}
main.h
#define NBLOCK 9
#define BLOCK_CELLS 9
void swap_rows(char**, int, int);
shuffle.c
#include <string.h>
#include "main.h"
void swap_rows(char **table, int r1, int r2) {
char tmp[BLOCK_CELLS];
size_t size = sizeof(char) * BLOCK_CELLS;
memcpy(tmp, table[r1], size);
memcpy(table[r1], table[r2], size); /* SIGSEGV here */
memcpy(table[r2], tmp, size);
}
Segmentation fault occurs inside swap_rows
function. Out of three memcpy
calls shown above, the first one works as expected. I commented out the last two memcpy
calls and added below line:
table[0][0] = 'z';
But, segmentation fault occurred again. Why I am not allowed to override values of table
in swap_rows
function?
Upvotes: 3
Views: 313
Reputation: 144951
In your code table
is not defined as a 2D array of char
, it is an array of pointers to char
initialized with pointers to string literals, which must not be modified.
You get a segmentation fault because the string literals are stored in read-only memory protected by the operating system.
You should either swap the pointers in swap_rows
or define table
as a real 2D array and swap the rows with an appropriate prototype:
#include <stdlib.h>
//#include "main.h"
#define NBLOCK 9
#define BLOCK_CELLS 9
void swap_rows(char table[][BLOCK_CELLS], int, int);
char table[NBLOCK][BLOCK_CELLS] = {
"abcdefghi",
"defghiabc",
"ghiabcdef",
"bcaefdhig",
"efdhigbca",
"higbcaefd",
"cabfdeigh",
"fdeighcab",
"ighcabfde",
};
int main() {
swap_rows(table, 0, 2);
return 0;
}
void swap_rows(char table[][BLOCK_CELLS], int r1, int r2) {
char tmp[BLOCK_CELLS];
size_t size = sizeof(tmp);
memcpy(tmp, table[r1], size);
memcpy(table[r1], table[r2], size);
memcpy(table[r2], tmp, size);
}
Upvotes: 3
Reputation: 75062
You are not allowed to modify string literals. For more information, see c - Why do I get a segmentation fault when writing to a "char *s" initialized with a string literal, but not "char s[]"?.
You can modify values of pointers to swap rows.
void swap_rows(char **table, int r1, int r2) {
char* tmp;
tmp = table[r1];
table[r1] = table[r2];
table[r2] = tmp;
}
If you prefer to use memcpy()
:
void swap_rows(char **table, int r1, int r2) {
char* tmp;
size_t size = sizeof(tmp);
memcpy(&tmp, &table[r1], size);
memcpy(&table[r1], &table[r2], size);
memcpy(&table[r2], &tmp, size);
}
Upvotes: 3