So as a part of a class project, I'm supposed to receive an input string from the user and to varies actions on it. For some reason, I get a stack corrupted error in the following code.
void main()
{
char cmd[80] = "", substr[81] = "", matrixName1[11], matrixName2[11], substrFrob[11] = "";
int start = 0, end = 0, cmdSort, i, j, prog = 0, row = 0, col, row1, row2, col1, col2, **matrix1, **matrix2, trace = 0, words, matrixNum = 0;
memset(matrixName1, 0, strlen(matrixName1)); //reseting variables
memset(matrixName2, 0, strlen(matrixName2));
printf_s("#");
fgets(cmd, sizeof(cmd), stdin);
words = wordCounter(cmd);
start = end;
stringCutter(substr, cmd, &start, &end);
while (1)
{
if (prog == 0) //sorting for command and number of args
{
if (!strcmp(substr, "exit") && words == 1) break;
else if (!strcmp(substr, "zeroes") && words == 4) cmdSort = 1;
else if (!strcmp(substr, "set") && words > 1) cmdSort = 2;
else if (!strcmp(substr, "echo") && words == 2) cmdSort = 3;
else if (!strcmp(substr, "frob") && words == 3) cmdSort = 4;
/* rest of the code*/
if (matrixName1[0] != 0) //freeing memory
{
for (i = 0; i < row1; i++)
free(matrix1[i]);
free(matrix1);
}
if (matrixName2[0] != 0)
{
for (i = 0; i < row2; i++)
free(matrix2[i]);
free(matrix2);
}
//system("cls");
//exit(0);
now as a part of the project we can't use any function within stdlib.h expect malloc and free. once I removed the exit(0), I started to receive an error when the user enters "exit" -
"Run time check Failure #2 stack around the variable 'substr' was corrupted"
but for the life of me, I can't find whats wrong.
thank in advence.
I couldn't check your code but it's likely that you are not allocating enough space for the char arrays. Trying to write to the char array that was not previously allocated can corrupt stack cookies hence the error.
If you had provided the full code I would try running it. In this case I can only guess :)
Edit: You might not be using the strlen right. You should be using "sizeof(char) * charcount " instead on memset calls.
Related
Im writing my own simplified version of the classic UNIX program 'wc' (word count). It counts number of lines, words, and characters. All these features work fine. But where i run into trouble is when im trying to read multiple files from *argv[x]. I need to make every variable into an array, and run the whole process through loops to achieve what im looking for.
My program returns a segmentation fault. Something is not being assigned into the arrays at some point in the code, and i can't seem to figure out exactly where that is.
Any help is much appreciated :)
/*
* [PROGRAM] wc (word count)
* [AUTHOR] Jesper M. Olsen # jm0.codes
* [DATE] September 9th 2015
* [PURPOSE] Returns number of lines, words, and characters in a file
*
* [DESCRIPTION] This program is meant to be utilized as a handy little browsing tool.
* For instance, while moving through the filesystem of a programming archive,
* just type 'wc <filename>' and you will get number of lines, words and characters returned promptly.
*/
#include <stdio.h>
#include <string.h>
int main(int argc, char *argv[])
{
if (argc == 1)
return -1;
int numL[argc]; /* initialize array value placeholders */
int numW[argc];
int numC[argc];
int getC[argc];
int getW[argc];
int setNull;
for (setNull = 1; setNull <= argc-1; setNull++) { /* assign ZERO to value placeholders */
numL[setNull] = 0;
numW[setNull] = 0;
numC[setNull] = 0;
getW[setNull] = 0;
}
int x;
FILE *fOp[argc-1];
for (x = 1; x <= argc-1; x++) { /* open file stream for each file */
fOp[x] = fopen(argv[x], "r");
if (fOp[x] == NULL)
return -1;
}
int y;
for (y = 1; (getC[y] = getc(fOp[y])) != EOF; y++) {
if (getC[y] == '\n') numL[y]++;
if (getC[y] == ' ' || getC[y] == '\n' || getC[y] == '\t') getW[y] = 0;
else if (getW[y] == 0) {
getW[y] = 1;
numW[y]++;
} numC[y]++;
}
int z;
for (z = 1; z <= argc-1; z++) { /* close files */
fclose(fOp[z]);
}
int c;
for (c = 1; c <= argc-1; c++) {
printf("[%s] %dL %dW %dC\n", argv[c], numL[c], numW[c], numC[c]);
}
return 0;
}
This will cause a segfault when you reach the last file
FILE *fOp[argc-1];
for (x = 1; x <= argc-1; x++) { /* open file stream for each file */
fOp[x] = fopen(argv[x], "r");
if (fOp[x] == NULL)
return -1;
}
because the array is not large enough. It should be
FILE *fOp[argc];
The mistake would be easier to see if you used
< argc
instead of
<= argc-1
in your loops.
I think problem may be
here -
for (y = 1; (getC[y] = getc(fOp[y])) != EOF; y++) {
if (getC[y] == '\n') numL[y]++;
if (getC[y] == ' ' || getC[y] == '\n' || getC[y] == '\t') getW[y] = 0;
else if (getW[y] == 0) {
getW[y] = 1;
numW[y]++;
} numC[y]++;
}
As arrays can argc number of elements but with this loop you may have read and stored integers more than argc in getC . Thus getting Seg Fault .
But we don't know what it inside files we can't be sure.
Try increasing size of arrays .
Note - It is better to initialize array starting with index 0. In this code you haven't use index 0.
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.
The fgetsstatement is not gathering anything from the calendarLog file stream into the events[][] array. My calendarLog.txt has five lines in it:
1/1/1 fds
2/2/2 dsa
3/3/3 sal
4/4/4 444
5/5/5 555
The printf statement is instructed to output one ! as well as the events[counter], however, my output statement is only the question marks, !!!!!, five of them (if I add more lines to calendarLog, it prints more exclamation points). Why does
while(fgets(events[counter++], EVENT_DESCR_SIZE, calendarLog) != NULL)
remain true and yet printf("!%s", events[counter]) not print the events[counter]?
All help appreciated!
FILE *calendarLog;
char events[MAX_EVENTS][EVENT_DESCR_SIZE],
*newLinePos;
int counter = 0,
index1,
index2;
for (index1 = 0; index1 < MAX_EVENTS; index1++)
for (index2 = 0; index2 < EVENT_DESCR_SIZE; index2++)
events[index1][index2] = 0;
if ((calendarLog = fopen("calendarLog.txt", "r")) == NULL)
{
calendarLog = (fopen("calendarLog.txt", "w"));
fprintf(calendarLog, "s\n", eventObject);
}
else
{
while (fgets(events[counter++], EVENT_DESCR_SIZE, calendarLog) != NULL)
{
if ((newLinePos = strchr(events[counter], '\n')) != NULL) //takes the '\n' out
*newLinePos = '\0'; //of the events[counter]
printf("!%s", events[counter]);
}
This should tell you everything you need to know about how to fix the problem:
FILE *calendarLog;
char events[MAX_EVENTS][EVENT_DESCR_SIZE];
char *newLinePos;
int counter = 0;
int index1;
int index2;
// initialize the array: events[][]
for (index1 = 0; index1 < MAX_EVENTS; index1++)
for (index2 = 0; index2 < EVENT_DESCR_SIZE; index2++)
events[index1][index2] = 0;
if ((calendarLog = fopen("calendarLog.txt", "r")) == NULL)
{ // fopen failed
calendarLog = (fopen("calendarLog.txt", "w"));
fprintf(calendarLog, "%s\n", eventObject); // 's' should be '%s
}
else
{ // fopen successful
while (fgets(events[counter++], EVENT_DESCR_SIZE, calendarLog) != NULL)
{
// following 'if' is looking at 'next' events because counter is already updated
// replace '\n' with null to terminate string for following printf
if ((newLinePos = strchr(events[counter], '\n')) != NULL)
*newLinePos = '\0';
// print the value
printf("!%s", events[counter]);
}
}
So I'm writing code to put strings into arrays and it's working perfectly, however I want it to terminate the reading of the strings when I hit a ## in the file. I'm running a loop and parsing the strings line by line. Within my string parser I put a loop to check for the ##. It's at the very end of my parser function and it goes:
for (i = 0; i < strlen(line)); i++)
{
if ((buffer[i] == '#') && (buffer[i+1] == '#'))
{
return -1;
}
}
The problem is that when it hits the line with the ## at the end it doesn't parse the string into my array. It seems like it's just ignoring the code before this loop.
As additional information I'm using strtok to put the tokens in positions in my char* array before this for loop.
EDIT: Here's my parseString function:
int parseString(char* line, char*** inString)
{
char* buffer;
int Token, i;
buffer = (char*) malloc(strlen(line) * sizeof(char));
strcpy(buffer,line);
(*inString) = (char**) malloc(MAX_TOKS * sizeof(char**));
Token = 0;
(*inString)[Token++] = strtok(buffer, DELIMITERS);
while ((((*inString)[token] = strtok(NULL, DELIMITERS)) != NULL) && (Token < MAX_TOKS))
Token++;
for(i=0; i<strlen(line); i++)
{
if ((buffer[i] == '#') && (buffer[i+1] == '#'))
{
return -1;
}
}
return Token;
}
First of all, you are reading out of bounds on an array, because array[-1] is not good. Secondly, use a variable to hold the string length, as the way you do it causes the for loop to re-evaluate strlen(line) for each iteration.
Now, for your problem, it seems like you're putting it before the code that adds it to an array. If you could give us a bit more code, that would help.
Insufficient buffer allocation
// buffer = (char*) malloc(strlen(line) * sizeof(char));
buffer = malloc(strlen(line) + 1); // +1 for the \0
strcpy(buffer,line);
Memory Leak
The allocated 'buffer' may be lost. The *inString array_ have a pointer to the beginning of 'buffer', allowing it to be freed in the calling routine, but that is iffy. Suggest using first element of *inString to save that buffer explicitly.
Algorithm hole
(*inString)[token-1] == NULL should be asserted before for().
O(n*n) via strlen()
Suggestion:
// for(i=0; i<strlen(line); i++)
int length = strlen(line); // `length` should be used in `malloc()` too.
for(i=0; i<length; i++)
OP's early edit approach was almost OK
Just needed to start indexing at 1, rather than 0. No need to test every index i of line, but (length-1). So (i = 1; i<length; i++) or (i = 0; i<length-1; i++).
// for (i = 0; i < strlen(line)); i++) {
int length = strlen(line);
for (i = 1; i<length; i++) { // start at 1
if ((buffer[i-1] == '#') && (buffer[i] == '#')) {
return -1;
}
}
For better assistance, recommend OP provide sample line, line with the ## at the end, MAX_TOKS and DELIMITERS.
Im trying to work with the example in the K and R book for this topic, but struggling.
I want an array of Char Arrays, whereby each element of the 'Father' Array points to an array of characters (string). Basically, I am reading from a file, line at a time, storing each line into an array, and then trying to store that array, into another array, which I can then sort via qsort.
But I can't seem to get anywhere with this! Anyhelp on my code is much appreciated, i.e. where to go from where I am!
EDIT: The problem is, the printing function isn't printing out my words that should be within the array of arrays, instead its just printing garbage, the main problem is, I'm not sure whether i am de-referencing things correctly, or not at all, whether I am adding it to the array of arrays correctly etc.
Regards.
#define MAXLINES 5000 /* max no. lines to be stored */
#define MAXLEN 1000 /* max length of single line */
char *lineptr[MAXLINES];
void writelines(char *lineptr[], int nlines);
int main(int argc, char *argv[]) {
int nlines = 0, i, j, k;
char line[MAXLEN];
FILE *fpIn;
fpIn = fopen(argv[1], "rb");
while((fgets(line, 65, fpIn)) != NULL) {
j = strlen(line);
if (j > 0 && (line[j-1] == '\n')) {
line[j-1] = '\0';
}
if (j > 8) {
lineptr[nlines++] = line;
}
}
for(i = 0; i < nlines; i++)
printf("%s\n", lineptr[i] );
return 0;
}
A problem is that line[MAXLEN] is an automatic variable, and so each time through the while loop it refers to the same array. You should dynamically allocate line each time through the while loop (line = calloc(MAXLEN, sizeof(char)) before calling fgets). Otherwise fgets always writes to the same memory location and lineptr always points to the same array.
Dan definitely found one error, the identical storage. But I think there are more bugs here:
while((fgets(line, 65, fpIn)) != NULL) {
Why only 65? You've got MAXLEN space to work with, you might as well let your input be a bit longer.
j = strlen(line);
if (j > 0 && (line[j-1] == '\n')) {
line[j-1] = '\0';
}
if (j > 8) {
lineptr[nlines++] = line;
}
}
Why exactly j > 8? Are you supposed to be throwing away short lines? Don't forget to deallocate the memory for the line in this case, once you've moved to the dynamic allocation that Dan suggests.
Update
ott recommends strdup(3) -- this would be easy to fit into your existing system:
while((fgets(line, 65, fpIn)) != NULL) {
j = strlen(line);
if (j > 0 && (line[j-1] == '\n')) {
line[j-1] = '\0';
}
if (j > 8) {
lineptr[nlines++] = strdup(line);
}
}
Dan recommended calloc(3), that would be only slightly more work:
line = calloc(MAXLINE, sizeof char);
while((fgets(line, 65, fpIn)) != NULL) {
j = strlen(line);
if (j > 0 && (line[j-1] == '\n')) {
line[j-1] = '\0';
}
if (j > 8) {
lineptr[nlines++] = line;
line = calloc(MAXLINE, sizeof char);
}
}
Of course, both these approaches will blow up if the memory allocation fails --
checking error returns from memory allocation is always a good idea. And
there's something distinctly unbeautiful about the second mechanism.