Segmentation Fault when accessing string array modified by a function in C - c

In my main, I define a pointer to an array of filename strings (that are to be determined):
char **commands = NULL;
I then call a function which populates the array based on argc & argv using getopt(). Before I return from the function, I print the list of files in the array and it works fine.
Back in my main, I attempt to print the same list (as confirmation) but I get a segmentation error which I can't figure out how to fix. I've included my code below.
Can someone please help me understand why commands in my main is not able to access the file list.
Cheers,
Nap
Here is the function that builds the list of file names:
int getInput (int argc, char **argv, const char *optionList, int *number, int *showEnds, char **commands, int *numberCommands) {
char c;
opterr = 0; // Turn off automatic error messages.
while ( (c = getopt(argc, argv, optionList)) != -1) {
switch (c) {
case 'n':
*number = TRUE;
break;
case 'E':
*showEnds = TRUE;
break;
case '?':
printf("Invalid switch used \"%c\"\n", optopt);
return EXIT_FAILURE;
break;
default:
printf("Input error occurred");
return EXIT_FAILURE;
}
}
printf("optind = %d,%d\n",optind, argc);
commands = malloc(sizeof(char*) * (argc-1));
if (optind < argc) {
*numberCommands = (argc - optind);
int ndx = 1;
while (optind < argc) {
int arraySize = (ndx+1)*sizeof(char*);
commands = realloc (commands,arraySize);
if (commands == NULL) {
fprintf(stderr,"Realloc unsuccessful");
exit(EXIT_FAILURE);
}
int stringSize = strlen(argv[optind])+1;
commands[ndx] = malloc(stringSize);
if(commands[ndx]==NULL){
fprintf(stderr,"Malloc unsuccessful");
exit(EXIT_FAILURE);
}
strcpy(commands[ndx],argv[optind]);
ndx++;
optind++;
}
printf ("Done With Input\n");
for (int i=1; i<=*numberCommands; i++) {
printf ("%s\n",commands[i]);
}
}
return EXIT_SUCCESS;
}
Here is my main:
int main(int argc, char **argv) {
FILE *myInput;
FILE *myOutput;
int result;
const char availOptions[] = "nE";
// Option flags
int number = FALSE; // (Option n) number all output lines
int showEnds = FALSE; // (Option E) Show Ends
char **commands = NULL;
int numberCommands = 0;
// Set default to stdin/stdout.
myInput = stdin;
myOutput = stdout;
if (argc > 1) {
result = getInput(argc,argv, availOptions, &number, &showEnds, commands, &numberCommands);
if (result != EXIT_SUCCESS) {
exit(EXIT_FAILURE);
}
}
printf ("Number of files = %d\n", numberCommands);
for (int i=1; i<=numberCommands; i++) {
printf ("%s\n",commands[i]);
}
echoInput(myInput, myOutput);
}

You're passing in a copy of the double-pointer
char **commands;
into the function. When you malloc() memory for it, it's not updating the pointer in your main function, only your local copy of the double-pointer. Hence, you're attempting to deference a NULL pointer in main. You could instead pass in a pointer to the double-pointer (i.e. the function would take a triple-pointer), your code would work then.
You would need to dereference the triple-pointer inside the function like so:
*commands = malloc(sizeof(char*) * (argc-1));
Alternatively, make a new double-pointer inside your function, do your work (leaving the code in your function roughly as-is) and before you return, assign the memory back into the pointer passed in from main:
*commands = local_commands;

In this function:
int getInput (/* ... */, char **commands, int *numberCommands) {
/* ... */
commands = malloc(sizeof(char*) * (argc-1));
}
you accept a pointer-to-pointer-to-char parameter by value. Looking at the call site, we can see that value will always be (char**)NULL. The parameter is a local variable inside your function. Even though you change it, and even though the caller happens to have a variable with the same name, you never change the caller's copy.
If you want to change the caller's copy of commands, you need to pass the address of that variable to your function:
int getInput (/* ... */, char ***commands, int *numberCommands) {
/* ... */
*commands = malloc(sizeof(char*) * (argc-1));
}
Now the call site looks like this:
char **commands = NULL;
int numberCommands = 0;
/* ... */
if (argc > 1) {
result = getInput(/*...*/, &commands, &numberCommands);
if (result != EXIT_SUCCESS) {
exit(EXIT_FAILURE);
}
}
note that commands and numberCommands are the two out-parameters - that is, they're the parameters where the function should change your local variable - so you're using & to pass pointers to both of them.

Related

Warning: cast to pointer from integer of different size (char* = function())

I am trying to find a way to store the return value of this function...
int createDirectory() {
int buffer = 21; //variable holds buffer count
int pid = getpid(); //variable calls builtin C function to get process id
char* directory = malloc(buffer * sizeof(char)); //dynamically creates array of chars
char* prefix = "schmcory.rooms." ; //prefix is set to my user id and rooms
//counts characters and stores in buffer
snprintf(directory, buffer, "%s%d", prefix, pid);
//printf("%s\n", directory); //for testing purposes
struct stat st = {0}; //initialize system struct
//if statement checks if directory exists
if(stat(directory, &st) == -1) {
mkdir(directory, 0755); //creates directory
}
free(directory); //free dynamically allocated memory
return *directory;
}
...into this variable char* directory = createDirectory();
I am getting the below error:
cast to pointer from integer of different size
I have tried the following:
char* directory = (void*)createDirectory();
char* directory = (int)createDirectory();
char directory = createDirectory(); //compiles w/o warning but prints nothing
I am trying to print the results in my main function.
printf(directory);
2 issue with the code :
return value of the function is char * not int - char * createDirectory();
you do free before you return the pointer
here is the code working (Linux environment)
//free(directory);
return directory;
}
int main( int argc, const char* argv[] )
{
char* directory = createDirectory();
printf ("main says %s \n", directory);
free(directory);
}
If I understand correctly, you want to return the result of mkdir, not the string containing the path, switch to
int ret = -1;
if (stat(directory, &st) != -1) // Notice `!=` instead of `==`
{
ret = mkdir(directory, 0755);
if (ret == -1)
{
perror("mkdir")
}
}
free(directory);
return ret;
and the caller should do something like:
int dir;
if ((dir = createDirectory()) != -1)
{
... do your stuff with dir
}
else
{
... raise exception
}
EDIT:
It seems that you want to return something like: schmcory.rooms.49111
In this case, the prototype should be
char *createDirectory(void) { // Return a pointer to `char`
instead of
int createDirectory() {
But do not call free or you end up deleting the result:
free(directory); // Remove this line
and
return *directory;
should be
return directory; // Do not dereference, you don't want the first char, you want the whole string

trying to create an array of struct pointer but get heap/buffer/etc violation statistically

i have two structs
typedef enum { False = 0, True = 1 } bool;
//defenition of candy structure
typedef struct _Candy {
char candy_name[16];
bool vegan;
}Candy;
typedef struct _Child {
char child_name[16];
Candy *candy_of_child;
}Child;
now im trying to create an array of pointers that each one is Child type
[*Child,*Child...] etc
now i can initialize it i need to do it dynamically
the function that does in is:
int AllocateKidsArray(int NumOfKids, Child** ptr_to_child_arr) {
//=================================================
//"AllocateKidsArray" intializing an array of childrens
//Input: 1. int indicating the number of kids
// 2. pointer to an array of children
//Output: 1. return an int value {0}->Success {-1}->Failure
// 2. pointer to an empty initialized array of childerns
//=================================================
// array of length NumOfKids, consisting of Child pointers
Child **ptr_to_childs = malloc(NumOfKids * sizeof(Child*));
int i;
for (i = 0; i < NumOfKids; i++) {
ptr_to_childs[i] = malloc(sizeof(Child));
strncpy((*ptr_to_childs[i]).child_name, "", 16);
(*ptr_to_childs)[i].candy_of_child = NULL;
}
*ptr_to_child_arr = *ptr_to_childs;
//for (i = 0; i < NumOfKids; i++) {
// free(ptr_to_childs[i]);
//}
//free(ptr_to_childs);
return 0;
}
im calling it from the main in the following manner:
int main(int argc, char** argv) {
//=================================================
if (argc < 3) {
printf("Incorrect number of arguments. Please invoke the program \n\t./program.exe < input.txt> <output.txt> \n");
exit(1);
}
int i, lines, checker = 0;
Candy *test = NULL;
char* name_test = NULL;
char* candy_test = NULL;
char* line = "Tamar,Apple\n";
int* NumLinesFile = NULL;
Child *ArrayOfChild = NULL;
.
.
.
//GetNumLines check
printf("%s\n", argv[0]);
printf("%s\n", argv[1]);
printf("%s\n", argv[2]);
GetNumLines(argv[1], &NumLinesFile);
lines = *NumLinesFile;
*NumLinesFile = NULL;
printf("%d\n", lines);
//=================================================
//AllocateKidsArray check
//AllocateKidsArray(lines, &ArrayOfChild);
AllocateKidsArray(lines, &ArrayOfChild);
//ImportKidsArray check
ImportKidsArray(argv[1], lines, &ArrayOfChild);
for (i = 0; i < lines; i++) {
//ArrayOfChild[i].candy_of_child = (Candy*) malloc(sizeof(Candy*));
printf("%s,%s\n", ArrayOfChild[i].child_name, ArrayOfChild[i].candy_of_child->candy_name);
}
//=================================================
and im statistically get heap/buffer violation
i suspect this function but i dont know what is wrong with it.
after the init of the array i pass it to another function that fills it in:
int ImportKidsArray(char* file_addr, int num_kids, Child** array_of_kids_to_fill) {
//=================================================
//"ImportKidsArray" reads the file and assign each valid line to cell in the array
//Input: 1. string to a location of a file
// 2. int indicating the number of kids
// 3. pointer to an array of children
//Output: 1. return an int value {0}->Success {-1}->Failure
// 2. pointer to an initialized array of childerns
//=================================================
FILE *fp;
char character;
char line[32];
int i = 0, j = 1, checker = 0, arr_count = 0;
char* TempChild = NULL;
char* TempCandy = NULL;
Child *arr = *array_of_kids_to_fill;
fp = fopen(file_addr, "r");
// Check if file exists
if (fp == NULL) {
printf("Could not open file %s", file_addr);
return -1;
}
while (!feof(fp)) {
fgets(line, 32, fp);
checker = ParseLine(line, &TempChild, &TempCandy);
GetCandy(TempCandy, &(arr[arr_count].candy_of_child));
strncpy((arr[arr_count]).child_name, TempChild, 16);
arr_count++;
}
return 0;
}
please if anyone can help, it will save my life :)
You want to change to ArrayOfChild. Passing it's address from main().
Change it by appropriately de-referencing it.
*ptr_to_childs = malloc(NumOfKids * sizeof(Child));
Then do rest of the operation on *ptr_to_childs. That will retain the change that you made in the called function.
Also check the return value of malloc. And free(using free()) the memory dynamically allocated.
If you notice carefully you will see in the ArrayOfChild() function you are working with a local variable Child **ptr_to_childs. You certainly don't want that as that variable will not be alive when the function ends.
Also while (!feof(fp)) is not appropriate to use. Check this link for that.
Another thing is check the return value of char *fgets(char *str, int n, FILE *stream).
On success, the function returns the same str parameter. If the
End-of-File is encountered and no characters have been read, the
contents of str remain unchanged and a NULL is returned.

C: Returning String From Another Function

I'm new to C / pointers / memory management and am having trouble implementing a few functions for a project I'm working on.
In my builtins.c file, I have a function called printalias that is called to print all the alias names and corresponding values stored in my program. At the end, I want to print one of the alias names by retrieving it via another function called getal.
int x_printalias(int nargs, char *args[]) {
int i = 0;
// Loop through, print names and values
for(i = 0; i< 100; i++)
{
if(alias_names[i][0]!='\0' && !alias_disabled[i])
{
char * var = alias_names[i];
char * val = alias_vals[i];
fprintf(stderr,"%s = %s\n", var, val );
}
}
// This is where I want to retrieve the string from another function
char * hello = "brett";
hello = getal(hello);
fprintf(stderr,"Got alias for brett --> %s",hello);
return 0;
}
My getal function exists in my shellParser.c file and looks like this, generally performing the same looping and returning when it is found:
const char * getal(int nargs, char *args[])
{
fprintf(stderr,"\nRetrieving alias...\n");
int i = 0;
fprintf(stderr, "check1\n" );
fprintf(stderr,"Got args[0]: %s\n", args[0]);
while (alias_names[i][0]!='\0' && i < MAX_ALIAS_LENGTH ) // Find empty slot in variables array
{
fprintf(stderr, "check2\n" );
fprintf(stderr,"I is currently %i and current varible in slot is %s\n",i,alias_names[i]);
//strncpy(hello, variables[i], MAX_VAR_LENGTH); // Variable at current slot
if(strcmp(alias_names[i], args[0]) == 0) // If we have an entry, need to overwrite it
{
fprintf(stderr,"Found alias %s = %s at spot %i\n",args[0],alias_vals[i], i); // Not at end if here
return alias_vals[i];
}
i++;
}
fprintf(stderr, "check3\n" );
// Elided....
return '\0';
}
In the end of my printalias function, I want to test that this getal function is working by calling it on a hardcoded string "brett". However, when I call my printalias function from the command line, it makes it to the "Check 1" print statement and then simply quits without error or return value.
I think this has something to do with my memory management or incorrect declaration of variables with pointers. Can anybody spot something (or a lot of things) that I'm doing wrong here?
You must declarete list of argument for to call getal and it call with these
list.
And pointer of return values getal must be const char*
//....
// This is where I want to retrieve the string from another function
char * hello[] = {"brett"}; // this list argument for getal function
const char *strGetal;
strGetal = getal(1,hello);
fprintf(stderr,"Got alias for brett --> %s",strGetal);
return 0;
}
Example:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char** get_all(int argc, char **argv)
{
char *value;
char **values = NULL;
int i;
values = (char**) malloc(sizeof (char) * argc);
if (values == NULL) {
perror("malloc");
return NULL;
}
for (i = 0; i < argc; i++, argv++) {
value = strchr(*argv, ':');
values[i] = (value + 1);
}
return values;
}
int main()
{
char *args[] = {"key:a", "key:b", "key:c"};
char **values;
int i;
values = get_all(3, args);
for (i = 0; i < 3; i++) {
puts(values[i]);
}
return 0;
}

Thread 1: EXC_BAD_ACCESS (code=1, address=0x0) standard C memory issue

I'm writing code to compare two input files in standard C, using the Xcode IDE. I keep getting this error: Thread 1: EXC_BAD_ACCESS (code=1, address=0x0). I've done some reading on this and believe it to be a memory issue, but no matter what I try I can't seem to fix it (I've also tried making the structures dynamically using malloc and listed that at the bottom of the code). It's strange because it writes all of the data and then spits out that error at the end. The file format is something like this:
start(int)..stop(int) id(+ or -) now some stuff I don't care about for the rest of the line
I've just been testing this on a file with only + id's so the "-" aspect isn't part of the issue. Anyway I'm quite tired and have been staring at this for a few hours, so please forgive me if it doesn't make sense, I will update it after a few hours of sleep.
typedef struct
{
int start;
int stop;
char *strandID;
} location;
int main(int argc, const char * argv[])
{
if (argc != 4)
{
fprintf(stderr,
"Usage is ./a.out windowfile.txt genefile.txt outputFileName");
exit(-1);
}
//const vars
const char *windowInput = argv[1];
const char *geneInput = argv[2];
const char *outputfile = argv[3];
const int windowHeader = 9;
const int geneHeader = 3;
//get size of structures -- I have debugged and these work correctly, returning the size of my structure
const int posWsize = getSize(windowInput, "+", windowHeader);
const int negWsize = getSize(windowInput, "-", windowHeader);
const int posGsize = getSize(geneInput, "+", geneHeader);
const int negGsize = getSize(geneInput, "-", geneHeader);
//declare structs
location posWindow[posWsize];
location negWindow[negWsize];
location posGene[posGsize];
location negGene[negGsize];
//extract data here
getLocations(posWindow, negWindow, windowInput, windowHeader);
return 0;
}
void getLocations(location *posL, location *negL, const char *input,
const int header)
{
FILE *fileptr = NULL;
fileptr = fopen(input, "r"); //open file
if (fileptr == NULL)
{ //check for errors while opening
fprintf(stderr, "Error reading %s\n", input);
exit(-1);
}
char tmpLoc[20];
char tmpID[2];
int eofVar = 0;
int lineCount = 0;
while (lineCount < header)
{ //skip header and get to data
eofVar = fgetc(fileptr);
if (eofVar == '\n')
lineCount++;
}
int pCount = 0;
int nCount = 0;
while (eofVar != EOF)
{
fscanf(fileptr, "%s %s", tmpLoc, tmpID); //scan in first two strings
if (!strcmp(tmpID, "+"))
{ //if + strand
char *locTok = NULL;
locTok = strtok(tmpLoc, ".."); //tok and get values
posL[pCount].start = atoi(locTok);
locTok = strtok(NULL, "..");
posL[pCount].stop = atoi(locTok); //ERROR IS SHOWN HERE
posL[pCount].strandID = tmpID;
printf("start=%d\tstop=%d\tID=%s\tindex=%d\n", posL[pCount].start,
posL[pCount].stop, posL[pCount].strandID, pCount);
pCount++;
}
else if (!strcmp(tmpID, "-"))
{ //if - strand
char *locTok = NULL;
locTok = strtok(tmpLoc, ".."); //tok and get values
negL[nCount].start = atoi(locTok);
locTok = strtok(NULL, "..");
negL[nCount].stop = atoi(locTok);
negL[nCount].strandID = tmpID;
nCount++;
}
while ((eofVar = fgetc(fileptr)) != '\n')
{
if (eofVar == EOF)
break;
}
}
fclose(fileptr);
}
//dynamic way...same issue -- just replace this with the above if statement and use the create location function
if (!strcmp(tmpID, "+"))
{ //if + strand
int locStart;
int locStop;
locStart = atoi(strtok(tmpLoc, ".."));//tok and get values
locStop = atoi(strtok(NULL, ".."));
posL[pCount] = *createlocation(locStart, locStop, tmpID);
pCount++;
}
location *createlocation(int start, int stop, char *strandID)
{
location *tmp = NULL;
tmp = (location *) malloc(sizeof(location) * 1);
tmp->start = start;
tmp->stop = stop;
tmp->strandID = (char *) malloc(sizeof(char) * 2);
strcpy(tmp->strandID, strandID);
return tmp;
}
Check the return value of strtok.
In your code here
locTok = strtok(NULL, "..");
posL[pCount].stop = atoi(locTok); //ERROR IS SHOWN HERE
strtok is returning a NULL pointer and according to documentation,
A null pointer is returned if there are no tokens left to retrieve.
which matches my original guess that because the address code is 0x0 there's a NULL pointer deference somewhere.
Obviously, the following call to atoi is expecting a non-NULL pointer and crashes.
You Can Also Use Exception Breakpoint in Xcode.
An exception breakpoint tells the debugger to pause whenever a problem is encountered anywhere in your program, so you can evaluate your program's state before it crashes.
Go to the Breakpoint Navigation (Cmd+8), then click the + button in the bottom left and choose Add Exception Breakpoint. You can leave it there.
In my case, I was using the wrong block type. For some reason, a developer had marked a block as const id blockName = ^(Type variableName) { /* code */ } but unfortunately the Type mismatched . Because blockNamewas declared as typeid, the compiler could not warn me properly when I passed blockName` as an argument somewhere else, and this error happened at runtime instead.
For example:
const id callback = ^(ARTPaginatedResult<ARTMessage *> * _Nullable paginatedResult, ARTErrorInfo * _Nullable error) { /* code */
[channel setOptions:channelOptions callback:callback];
The block above has 3 parameters, but channel:setOptions:callback: defines 1 argument called callback, which must be a block which takes 1 argument, and is declared as
- (void)setOptions:(ARTRealtimeChannelOptions *_Nullable)options callback:(nullable void (^)(ARTErrorInfo *_Nullable))cb;
for xc
in your main() function, try to remove char*argv[] or both arguments.
You should delete the arguments of you main function. And it will work.

atof creates strange result

I am trying to use atof() to convert a string to a double (obviously), but the results are not what I expect. Here is the code and debug information about the variable values BEFORE atof():
d = atof (arg);
next.db = d;
*debug info*
arg = 0x0034f7b0 "10.0"
d = 0.0000000000000000
Once the program has stepped through atof(). the results are as follows:
arg = 0x0034f7b0 "ôþSÄ÷4"
d = 0.0000000000000000
As you can see, before the command, the arg variable does hold a valid double. Though, the return value is 0. What confuses me, is why does the value of arg change?
Also, I do have stdlib.h included. As well, arg is declared as:
char *arg;
If it helps at all, the "10.0" was read from a file.
More code:
void read_instructions()
{
char *str;
char *arg;
int n;
char c;
double d = 0;
instruction next = {0};
while (!feof(datafile)) {
// Fetch the next string
// if (push or pop), get the next argument
// create instructiwn and add to instruction array
str = get_next_string();
if (strncmp (str, "P", 1) == 0) {
if (strncmp (str, "PUSH", 4) == 0) {
next.func = pushFunc;
}
else {
next.func = popFunc;
}
arg = get_next_string();
n = arg[0];
if (n > 64 && n < 71)
next.ch = arg[0];
else {
d = atof (arg);
next.db = d;
}
instr[instr_count] = next;
instr_count++;
}
else {
c = str[0];
switch (c) {
case 'A' :
next.func = addFunc;
break;
case 'S' :
next.func = subFunc;
break;
case 'M' :
next.func = multFunc;
break;
case 'D' :
next.func = divFunc;
break;
case 'H' :
next.func = haltFunc;
default :
printf ("Invalid instruction");
}
instr[instr_count] = next;
instr_count++;
}
}
fclose (datafile);
}
This is the given code to open and access the file:
FILE *datafile;
int main(int argc, char *argv[])
{
if (argc != 2) {
printf("error, incorrect number of arguments");
haltFunc(instr[0]);
}
open_file(argv[1]);
read_instructions();
execute_instructions();
return 0;
}
void open_file(char* argv)
{
char buf[1024];
char cwd[512];
getcwd(cwd, sizeof cwd);
sprintf(buf, "%s\\%s", cwd, argv);
if (!(datafile = fopen(buf, "r"))) {
printf("Error: Make sure your file is located here:\n%s", buf);
}
}
char* get_next_string()
{
char str[15];
fscanf(datafile, "%s", &str);
return str;
}
The header file:
#ifndef MAIN_HEADER_H
#define MAIN_HEADER_H
#define INSTR_SIZE 30
typedef struct {
void (*func)(instruction);
union {
double db;
char ch;
};
} instruction;
int main(int, char*);
char* get_next_string();
void open_file(char*);
void read_instructions();
void execute_instructions();
void pushFunc(instruction instr);
void popFunc(instruction instr);
void addFunc(instruction instr);
void subFunc(instruction instr);
void multFunc(instruction instr);
void divFunc(instruction instr);
void haltFunc(instruction instr);
#endif
And this is the test file:
PUSH 10.0
PUSH 4.0
PUSH 7.0
PUSH 5.0
POP D
POP E
POP
PUSH D
ADD
PUSH 5.0
POP B
PUSH 17.0
POP E
PUSH B
PUSH E
SUB
HALT
Your problem is probably caused by the get_next_string() function returning a pointer to a temporary local character array. As soon as the function returns, the stack memory once used by str[] is being overwritten by some other automatic variable. That would explain why arg is being corrupted.
There are several possible fixes.
The caller could allocate memory to hold the string and pass this pointer to the function for it to fill with data.
The callee could allocate memory for the string and return that pointer. That also returns ownership to the caller and responsibility for calling free() when done.
The str[] array could be declared static inside the function. It would no longer be temporary but be aware that every time you call the function the previous string will be overwritten.

Resources