C segmentation error - c

#include <stdio.h>
void lergab(char *gab);
void criamatriz (char **alunoresp, int *resp);
int main(){
char gab[20];
char alunoresp [100][21];
int resp[80];
//lergab(&gab);
criamatriz (&alunoresp[100][21], &resp[80]);
printf ("\n\n%d\n", alunoresp[0][0]);
printf ("%c\n", alunoresp[0][1]);
printf ("%c\n", alunoresp[0][1]);
printf ("%c\n", alunoresp[0][19]);
return 0;
}
void lergab (char *gab){
int i;
for(i=0; i<20; i++)
scanf("%c\n" , &gab[i]);
printf("%c", gab[19]);
}
void criamatriz (char **alunoresp,int *resp){
int i = 0, j;
//for (i = 0; i <= 100; i++){
scanf ("%c", &alunoresp[i][0]);
for (j = 0; j < 80; j++){
scanf ("%d", &resp[j]);
}
for (j = 0; j < 80; j=j+4){
int g = 1;
if ((resp[j] + resp[j+1] + resp[j+2] + resp[j+3]) != 1)
alunoresp[i][g] = 'e';
else if (resp[j] == 1)
alunoresp[i][g] = 'a';
else if (resp[j+1] == 1)
alunoresp[i][g] = 'b';
else if (resp[j+2] == 1)
alunoresp[i][g] = 'c';
else if (resp[j+3] == 1)
alunoresp[i][g] = 'd';
g++;
}
//}
}
This code is supposed to read a number as ASCII code, then read 80 numbers and convert them to their respective character, like a electronic test scanner.
I.E:
0
0
1
0
is c,
1
0
0
0
is a,
1
0
1
0
is an invalid option (for you should only sign one answer per question).
Code is just a test, my objective here is create a matrix that contains 100 candidates with 20 answer in each of them, along with their identification code, which is the first number read as ASCII, thus alunoresp[100][21] is declared.
I'm getting segmentation error every time i try to run it on gcc, any ideas?
Edit:
Thanks for the help on the indices thing. I didn't notice.
Stil, even after fixing that i keep getting segmentation faults.
Code now looks like this:
#include <stdio.h>
void lergab(char *gab);
void criamatriz (char **alunoresp, int *resp);
int main(){
char gab[20];
char alunoresp [100][21];
int resp[80];
//lergab(&gab);
criamatriz (&alunoresp, &resp);
printf ("\n\n%d\n", alunoresp[0][0]);
printf ("%c\n", alunoresp[0][1]);
printf ("%c\n", alunoresp[0][1]);
printf ("%c\n", alunoresp[0][19]);
return 0;
}
void lergab (char *gab){
int i;
for(i=0; i<20; i++)
scanf("%c\n" , &gab[i]);
printf("%c", gab[19]);
}
void criamatriz (char **alunoresp,int *resp){
int i = 0, j;
//for (i = 0; i <= 100; i++){
scanf ("%c", &alunoresp[i][0]);
for (j = 0; j < 80; j++){
scanf ("%d", &resp[j]);
}
for (j = 0; j < 80; j=j+4){
int g = 1;
if ((resp[j] + resp[j+1] + resp[j+2] + resp[j+3]) != 1)
alunoresp[i][g] = 'e';
else if (resp[j] == 1)
alunoresp[i][g] = 'a';
else if (resp[j+1] == 1)
alunoresp[i][g] = 'b';
else if (resp[j+2] == 1)
alunoresp[i][g] = 'c';
else if (resp[j+3] == 1)
alunoresp[i][g] = 'd';
g++;
}
//}
}

There are two issues with your program:
You are calling criamatriz function incorrectly - rather than passing a pointer to the end of the arrays, you should be passing arrays themselves, and
Your criamatriz function takes a 2D array incorrectly - you are passing it like a pointer to a pointer, which is incorrect. You should be passing it like a pointer to an array of 21 elements.
Here is how you should declare and define your criamatriz function:
void criamatriz(char (*alunoresp)[21], int *resp);
Call it like this:
criamatriz(alunoresp, resp);

criamatriz (&alunoresp[100][21], &resp[80]);
^^^^^^^^^
You're exceeding the maximum allowed indeces in your array there. e.g.
int x[10]; // allows index 0->9

Welcome to SO, Lucas!
I'm getting segmentation error every time i try to run it on gcc, any ideas?
Step 0 is to get yourself a debugger, this won't be the last time you encounter a similar issue. If you're using gcc, it's a good bet that gdb is available on this system. Try running your executable with gdb and X marks the spot!
gdb ./my_binary
... then ..
run
execution will halt right where the invalid memory access occurred. You can examine the state of the program (local variables, etc) using the print command and you can walk up and down the stack with up and down respectively.
For example:
(gdb) run
Starting program: ./go
Program received signal SIGSEGV, Segmentation fault.
0x00000000004004fd in inner () at ./go.c:6
6 int ohno = *bad;
(gdb) bt
#0 0x00000000004004fd in inner () at ./go.c:6
#1 0x0000000000400512 in outer () at ./go.c:11
#2 0x000000000040052d in main (argc=1, argv=0x7fffffffdf88) at ./go.c:16
(gdb) backtrace
#0 0x00000000004004fd in inner () at ./go.c:6
#1 0x0000000000400512 in outer () at ./go.c:11
#2 0x000000000040052d in main (argc=1, argv=0x7fffffffdf88) at ./go.c:16

When sending an array to a function, all you need to do is send the base address of that array,
In your code
criamatriz (&alunoresp[100][21], &resp[80]);
this line is actually sending the address of the alunoresp[100][21] element, which doesnt even exist.
An array defined as int alunoresp[100][21] has maximum indices [99][20] since indices start from 0
You need to call the function like this,
criamatriz (alunoresp, resp);
Since the name of the array contains the base address (address poitning to the first element) of that array.

Related

Random Bytes In C Output

I just wrote my first program in C and it is a cesarean shift implementation. It works as expected with short inputs, but sometimes produces seemingly random bytes at the and of the output and I cannot figure out why.
I have tried looking at the program in GDB, but just don't have enough experience yet to figure out exactly what is going wrong. I would love to know how one would go about figuring this out with a debugger like GDB.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
void rot(char*, int);
char alphabet[27] = "abcdefghijklmnopqrstuvwxyz";
int main (int argc, char* argv[]) {
if (argc != 3) {
printf("Usage: %s [lowercase-text] [rotation-number]\n", argv[0]);
return 1;
} else {
rot(argv[1], atoi(argv[2]));
}
}
void rot (char* t, int r) {
char result[100];
for (int i = 0; i < strlen(t); i++) {
char* location = strchr(alphabet, t[i]);
result[i] = location ? alphabet[(location - alphabet + r) % strlen(alphabet)] : t[i];
}
printf("%s\n", result);
}
Here is the unexpected output. The actual rotation works fine but there are some unexpected bytes at the end.
michael#linux:~/Desktop$ ./rotation
Usage: ./rotation [lowercase-text] [rotation-number]
michael#linux:~/Desktop$ ./rotation rotations_are_cool 13
ebgngvbaf_ner_pbby��� (<- Why are these here ???)
Here was my attempt with GDB. I have not been able to identify the extra data tagging at the end. (full output # https://pastebin.com/uhWnj17e)
(gdb) break *rot+260
Breakpoint 1 at 0x936: file ../rot.c, line 25.
(gdb) r rotations_are_cool 13
Starting program: /home/michael/Desktop/rotation rotations_are_cool 13
Breakpoint 1, 0x0000555555554936 in rot (
t=0x7fffffffe2d2 "rotations_are_cool", r=13) at ../rot.c:25
25 printf("%s\n", result);
(gdb) x/s $rbp-0x80
0x7fffffffdde0: "ebgngvbaf_ner_pbby\377\367\377\177"
This strange occurrence only happens around 50% of the time and happens more often with longer strings. Please help explain and eliminate this. Any other tips that would improve my code are also appreciated. Thanks a dozen!
The end of a string is recognized by the character '\0'.
So you could do it like this
char result[100];
int i;
for (i = 0; i < strlen(t); i++) {
char* location = strchr(alphabet, t[i]);
result[i] = location ? alphabet[(location - alphabet + r) % strlen(alphabet)] : t[i];
}
result[i] = '\0';
You also don't check, that result is large enough for the string, so you could allocate the needed memory dynamically
size_t len = strlen(t)
char *result = malloc(len + 1); /* +1 for terminating '\0' character */
if(result == NULL) {
/* Error allocating memory */
}
int i;
for (i = 0; i < len; i++) {
char* location = strchr(alphabet, t[i]);
result[i] = location ? alphabet[(location - alphabet + r) % strlen(alphabet)] : t[i];
}
result[i] = '\0';
printf("%s\n", result);
free(result);

N permutations of string (with repetitions)

I have to print first n permutations with repetitions of a string.
String is formed with characters 'a','b','c','d','e','f'.
For example, first 10 permutations would be: aaaaaa,aaaaab,aaaaac,aaaaad,aaaaae,aaaaaf,aaaaba,aaaabb,aaaabc,aaaabd.
This is my failed attempt:
int main()
{
FILE *c;
c = fopen("C:\\Users\\Korisnik\\Desktop\\tekst\\permutacija.txt", "w");
char s[6] = "abcdef";
char t[6] = "aaaaaa";
s[6] = '\0';
t[6] = '\0';
int k = strlen(t);
int m = k;
int n;
scanf("%d", &n);
int br = 0;
int i = 0;
while (br < n) {
i = 0;
while (i < 6) {
t[k-1] = s[i];
fprintf(c, "%s ", t);
fprintf(c, "\n");
i++;
br++;
if (br == n) {
exit(1);
}
}
t[k-1] = 'a';
k--;
if (k < 0) {
k = m;
}
}
return 0;
}
And my output for first 10 permutations is:
aaaaa
aaaaab
aaaaac
aaaaad
aaaaae
aaaaaf
aaaa
aaaaba
aaaaca
aaaada
Any suggestions?
(Showing a different idea)If you look carefully you will see that all the permutations are the numbers in base-7. Consider a as 0, b as 1 and so on. So for every number 1..n you will convert it into base 7 and write it (By write it I mean, in place of 0 you put a,1 - b etc). That will give you the required result. (Ofcourse in conversion you will have to append 0 to the left of the number as per number of digits you want to show). There are problems in your code:
char s[6]="abcdef";
is legal in C.
s[6]=0;
This is not as you are accessing array index out of bound which is Undefined behavior. strlen(t) is undefined behavior as t is not NUL terminated.
Also you have fprintf(c,"%s ",t); in your code - this also leads to undefined behavior, it also expects a char* which points to a nul terminated char array. This will make your realize that how irrelevant it is to have something like this
char s[6]="abcdef";
Long story short, use char s[7]="abcdef"; (same applies to t also).

Function to search for string in array of strings

I am trying to write a function that searches for the unique part(maximum two characters) of a string in an array of strings. Although strstr and strchr are not working and crash my program for some reason. So I have resorted to trying to create something that resembles their function.
My question is this:
Why is strstr not working (something like strstr(lex[j],word)) and what am I doing wrong here?
Here is the code for the function that searches for two unique characters within an array of strings :
void convert(char word[])
{
int i;
for (i = 0 ; i <= strlen(word) ; i++)
{
if(word[i] >= 65 && word[i] <= 90)
{
word[i] = word[i]+32;
}
}
}
int twochar(char lex[50][50],char word[], int size,char temp[3])
{
int i,j,k,count,totlen;
convert(word);
for (i = 0 ; i < strlen(word) - 1 ; i++)
{
count = 0;
totlen = 0;
for(j = 0; j<size; j++)
{
convert(lex[j]);
totlen += strlen(lex[j]) - 1;
for(k = 0 ; k < strlen(lex[j]) - 1 ; k++)
{
if (word[i] != lex[j][k] || word[i+1] != lex[j][k + 1])
{
count++;
}
}
}
if(count = = totlen)
{
temp[0] = word[i];
temp[1] = word[i+1];
}
}
}
int main(int argc, char *argv[])
{
char lex[50][50] = {"word1","word2","word3","word4" }, word[] = "test";
char p[3];
twochar(lex,word,4,p);
printf("%c%c\n",p[0],p[1]);
return 0;
}
this line:
for(k=0;k<strlen(lex[j])-1;k++)
is the problem.
strlen(lex[0]) is 0
strlen(lex[0])-1 is -1 (0xFFFFFFFF in a 32 bit system)
k starts at 0 and is incremented until it is equal to 0xFFFFFFFF
of course, k exceeds the bounds of lex[0] when k = 50.
the result is undefined behaviour which leads to the seg fault event
To determine all the above, I compiled/linked the program via gcc, with the -ggdb parameter.
then I ran the program via 'gdb theprogram'
within gdb I entered
br main <-- break point set
run
c <-- continue
the program then crashed with a seg fault event
then I entered
bt <-- back trace
the bt showed me this line: 'if(word[i]!=lex[j][k] || word[i+1]!=lex[j] [k+1])'
Then I entered
p k <-- print variable k
=6832 (which is WAY out of bounds)
then I entered
run
y
br theprogram.c:41 (the line number from above) <-- set another break epoint
c
the program stopped at line 41
p j
=0 ( this was the gdb response )
p k
= 0
p i
= 0
a little thinking,
stepping though that inner loop using 'n' <-- next
and playing on gdb
indicated that the problem was in line 42
and resulted in revealing the root of the problem

Segfault in c program

I have a segmentation fault upon executing this program and all I know is that segfault is happening after two of the gets commands and after the next scanf command. I know gets isn't good command to use in here but my university is using it so... Here is the code of my main function and functions that program uses and I would appreciate if someone could said to me where the problem persists. The code is written in croatian but nothing really particular isnt said in there so don't mind that
My main program
#include <stdio.h>
#include "funkcije.h"
#define MAX 300
int main (void) {
char niz1[MAX+1], podniz[6], niz2[MAX+1];
int dulj_pod = 0, kontrola, duljina1 = 0, duljina2 = 0, kraj, brojac = 0, i;
float slicnost;
printf("Ucitaj prvi niz > ");
gets(niz1);
printf("Ucitaj drugi niz > ");
gets(niz2);
while (niz1[duljina1] != '\0')
duljina1++;
while (niz2[duljina2] != '\0')
duljina2++;
printf("Ucitaj duljinu podniza : ");
do {
scanf("%d", &dulj_pod);
} while ((dulj_pod < 2 || dulj_pod > 5) || (dulj_pod > duljina1 || dulj_pod > duljina2));
kraj = duljina1 - dulj_pod;
for (i=0; i<=kraj; i++) {
genPodniz (niz1, podniz, i, dulj_pod);
kontrola = sadrziPodniz (niz2, podniz);
if (kontrola == 1)
brojac++;
}
slicnost = (float)brojac / (kraj+1);
printf("Prvi niz : %s\nDrugi niz : %s\nDuljina podniza za usporedbu nizova : %d\n", niz1, niz2, dulj_pod);
printf("Slicnost nizova '%s' i '%s' iznosi %f.\n", niz1, niz2, slicnost);
return 0;
}'
And functions
#include "funkcije.h"
void genPodniz (char *niz, char *podNiz, int pocPozicija, int duljPodniz) {
int i, j=0;
for (i=0; i<duljPodniz; i++, j++) {
*(podNiz+j) = *(niz+pocPozicija+i);
}
*(podNiz+j) = '\0';
}
int sadrziPodniz (char *niz, char *podNiz) {
int kontrola, i = 0, j = 0, duljina1 = 0, duljina2 = 0, poz = 0;
while (*(niz+duljina1) != '\0')
duljina1++;
while (*(niz+duljina2) != '\0')
duljina2++;
while (j < duljina2) {
if (*(niz+i) == *(podNiz+j)) {
kontrola = 1;
i++;
j++;
}
else {
kontrola = 0;
j = 0;
++poz;
i = poz;
}
}
return kontrola;
}
First - find out how to run this code under a debugger. Then it'll just stop on the line where the segfault occurs, which should make it more-obvious what the problem is. Given that you're saying "segfault", it's probably safe to assume you're running some unix-variant, in which case, "gdb" is probably your debugger.
Second - a segfault is, maybe 90% of the time, due to overrunning the bounds of allocated memory. Since your program isn't allocating any memory with "malloc", that means you're writing past the end of one of your arrays. Chances are, one of your loops is running way too many times, and accessing past the end of an array.

Segmentation fault using arrays

Well, I've been at this forever and I know exactly where the fault is, but no clue how to fix it. I already know fgets and scanf would be better for this program, but I can't do that.
The program worked about 10 minutes ago, then I changed it and got a seg fault. Then I changed it back and still got a seg fault. Anyway, I'm sure the fresh eyes will see it right away. Have at it :D
PS: Please note my (lessthan) instead of < because I don't know how to properly leave those in my code examples still :(
#define WORDLENGTH 15
#define MAXLINE 1000
int main()
{
char *line[MAXLINE];
int i = 0;
int j;
int n;
char c;
for (n=0; c!=EOF; n++){
char *tmp = (char *) malloc(sizeof(char)*WORDLENGTH);
while ((c=getchar())!=' ')
tmp[i++]=c;
line[n]=tmp;
i=0;
printf("\n%s\n",line[n]); //
}
for(j = 0; j < n; j++){
printf("\n%s\n", line[j]);
free (line[j]);
}
return 0;
}
you are doing line[n++] = tmp. And then accessing line[n] after that. But line[n] hasn't been assigned.
To change it, you can print line[n-1] instead, but clearer would be:
line[n] = tmp;
i = 0;
printf(... line[n]);
and place the increment in the for statement instead i.e. for (n = 0; c != EOF; n++).
EDIT
This is a summary of what I would do:
Place the i=0 assignment at the start of the loop. Logically, it is an initialization of i and currently it is done in two places (at int i = 0; and after the assignment of line[n]). Both places are not near where one would expect an initialization of a variable used in the while loop to be.
Guard against nonsense input by checking that i does not exceed WORDLENGTH-1. Actually, I would probably code the inner while loop as a for loop on i like so:
for (i = 0; i < WORDLENGTH; i++) {
tmp[i] = getchar();
if (tmp[i] == ' ') break;
}
tmp[i] = 0;
or (in my character) for(i = 0; i < WORDLENGTH; ++i) if ((tmp[i] = getchar()) == ' ') break; followed by..
tmp[i] = 0 to NUL-terminate the string. Since malloc doesn't necessarily return a 0-filled memory block.
there are still bugs in the suggested solution !
malloc() can fail and return a NULL pointer
at the end of the for () the maximum i value is WORDLENGTH
so this assignment isn't correct ( out of bounds )
tmp[i]= 0;
Can fix both with
char *tmp = (char *) malloc( sizeof(char) * (WORDLENGTH + 1) );
if ( tmp == NULL ) // end of available memory
break;
moreover, it isn't clear if you allow EOF inside the last string.

Resources