In my program, the function read_commands just gets 2 strings and puts it into the struct Commands and returns the filled struct.
Apparently I have some fault in my logic. I'm getting the error:
Invalid read size of 1
In valgrind.
typedef struct{
Command *test
Command *compile
}Commands;
typedef struct Command{
char *command;
struct Command *next;
}Command;
I just do read_commands("abc", "abc");
The rest of my code:
Commands read_commands(const char *compile_cmds, const char *test_cmds) {
Commands commands;
Command *compile, *test;
int i;
if (compile_cmds == NULL || test_cmds == NULL)
exit(0);
compile = commands.compile;
test = commands.test;
i = 0;
while (compile_cmds + i != NULL) {
compile = malloc(sizeof(Command));
compile->command = malloc(strlen((compile_cmds + i) + 1));
strcpy(compile->command, compile_cmds + i);
compile = compile->next;
i++;
}
i = 0;
while (test_cmds + i != NULL) {
test = malloc(sizeof(Command));
test->command = malloc(strlen((test_cmds + i) + 1));
strcpy(test->command, test_cmds + i);
test = test->next;
i++;
}
return commands;
}
You should change the arguments to accept multiple commands e.g.
Commands read_commands(const char** compile_cmds, const char** test_cmds)
then you call it with:
char* compileCmds[] = { "abc", NULL };
char* testCmds[] = { "abc", NULL };
Commands c = read_commands(compileCmds,testCmds);
Meanwhile in your function to get all "compile" commands:
Commands commands = { NULL, NULL };
...
Command* last = NULL;
for (i = 0; compile_cmds[i] != NULL; ++i)
{
compile = malloc(sizeof(Command));
// check if we have added before, or if it is the first compile command
if (last!=NULL)
{
// last command, so append
last->next = compile;
}
else
{
// first command, set as first
commands->compile = compile;
}
// add the payload
compile->command = strdup(compile_cmds[i]);
compile->next = NULL;
// keep track of last to easy append
last = compile;
}
...
you may have noticed you have duplicate code in your function, so an idea would be to create a function read_commands for one of the compile or tests at a time and call it twice instead.
e.g.
read_commands(Command** cmd, const char** cmds);
...
Commands c = {NULL,NULL};
read_commands(&c.compile, compileCmds);
read_commands(&c.test, testCmds);
the extra * is for to be able to change what the pointer points to
read_commands(Command** pc, const char* cmds)
{
...
*pc = malloc(sizeof(Command));
...
}
Related
I am making an INI parser that will save all sections in an array for later use. The problem I am running into is in SECTION_OPEN. I call ini_init() which causes the first line of the function to crash with a Segmentation Fault. I am known for putting many memory leaks in my code, but after looking through, I haven't figured out a way to get around this.
I have tried:
Giving many different mallocs over 100000 to work with, which still crashes
Commenting out code and slowly un-commenting to see what is crashing
test.ini:
; This is a valid comment
; Global variables work
var = 1
var2 = 2
var3 = 3
[Test1] ; Section
name = Primitive
organization = PrimOS
test = var
another = test
once_again=another_test
; Will check to see if variables work as intended
[.Test2] ; Subsection
; This variable will crash
another_organization = %name%
; This test will crash
[Test3] ; Section
another_name = "This is me"
ini.h
#ifndef SEAWARE_INI_H
#define SEAWARE_INI_H
#define MAX_HOLDING_CELL 255
#define MAX_LINE_LENGTH 255
// Syntax
#define QUOTES '"'
#define SECTION_OPEN '['
#define SUBSECTION '.'
#define SECTION_CLOSE ']'
#define VARIABLE_CALL '%'
#define COMMENT ';'
#define EQUALS '='
#define EQUALS_PTR "="
// Only one variableType for each variable
struct variable {
char * variableName;
char * value;
};
// The magic...
struct INI {
// If NULL, you are global
char * sectionName;
// Like [.Test] or [Test1.Test]
struct INI ** subSections;
// Self explanitory
struct variable ** variables;
int subSectionsPtr;
int variablesPtr;
struct INI * nextSection;
struct INI * prevSection;
};
struct INI * ini_init();
struct INI * interpret(struct INI * ini, char * filePath);
#endif
ini.c
#include <ini.h>
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>
#include <stdio.h>
// Global functions
// Sets up new struct INI * variable
struct INI * ini_init() {
// Crashes
struct INI * newINI = malloc(sizeof(struct INI));
newINI->variablesPtr = 0;
newINI->subSectionsPtr = 0;
newINI->variables = malloc(sizeof(struct variable*)*(newINI->variablesPtr+1));
newINI->subSections = malloc(sizeof(struct INI *)*(newINI->subSectionsPtr+1));
*newINI->variables = NULL;
*newINI->subSections = NULL;
newINI->sectionName = NULL;
newINI->nextSection = NULL;
newINI->prevSection = NULL;
return newINI;
}
// Interprets an INI file, with syntax defined in ../include/ini.h
struct INI * interpret(struct INI * ini, char * filePath) {
// Loop Variables
char line[MAX_LINE_LENGTH];
FILE * iniFile = fopen(filePath, "r");
bool isSubsection = false;
// Read line by line
while(fgets(line, sizeof(line), iniFile)) {
bool isComment = false;
bool isQuoted = false;
// A holding cell for all the bad defaults out there, stay safe out there...
char holdingCell[MAX_HOLDING_CELL];
int holdingCellPtr = 0;
// For each character in line
for (int i = 0; i < strlen(line); i++) {
printf("%c", line[i]);
// Prevents memory leaks in holdingCell
holdingCell[holdingCellPtr] = '\0';
// Interpret
switch(line[i]) {
// Move into section
case SECTION_OPEN: {
// If you are in a subsection, get out of it
if (isSubsection == true) {
ini = ini->prevSection;
isSubsection = false;
}
struct INI * newSection = ini_init();
if (line[(i+1)]==SUBSECTION) {
isSubsection = true;
// Reallocate size of subSections array
ini->subSections = realloc(ini->subSections, sizeof(struct INI *) * (ini->subSectionsPtr+1));
// Set new subsection and enter it
newSection->prevSection = ini;
ini->subSections[ini->subSectionsPtr] = newSection;
ini->subSectionsPtr++;
ini = ini->subSections[ini->subSectionsPtr];
i++;
}
else {
// Create new section and go into it
newSection->prevSection = ini;
ini->nextSection = newSection;
ini = ini->nextSection;
ini->nextSection = NULL;
}
break;
}
// Set sectionName
case SECTION_CLOSE: {
ini->sectionName = malloc(sizeof(char) * strlen(holdingCell));
strcpy(ini->sectionName, holdingCell);
break;
}
// Creates new variable and assigns name and value
case EQUALS: {
isQuoted = true;
struct variable * newVar = malloc(sizeof(struct variable)*(ini->variablesPtr+6));
char * value = strtok(line, EQUALS_PTR);
// Set variableName
newVar->variableName = malloc(sizeof(char)*strlen(value));
strcpy(newVar->variableName, value);
// After EQUALS
value = strtok(NULL, EQUALS_PTR);
// Set value
newVar->value = malloc(sizeof(char)*strlen(value));
strcpy(newVar->value, value);
printf("%s", value);
// Add variable to ini field
ini->variables = realloc(ini->variables, sizeof(struct variable*)*(ini->variablesPtr+1));
ini->variables[ini->variablesPtr] = newVar;
ini->variablesPtr++;
break;
}
// Skips to new line
case COMMENT: {
isComment = true;
break;
}
// Gets names and values
default: {
holdingCell[holdingCellPtr] = line[i];
holdingCellPtr++;
break;
}
}
if (isComment == true || isQuoted == true)
break;
}
}
// Stop reading file
fclose(iniFile);
// Loop back to beginning
while(ini->prevSection != NULL) {
ini = ini->prevSection;
}
// You get what you get, stop throwing a fit
return ini;
}
There are several malloc's that call strlen.
strlen does not count the terminating zero.
strcpy copies the terminating zero. Since the allocated memory does not include the terminating zero, it is written outside the allocation. Something gets corrupted.
This can be fixed by allocating strlen() + 1
For example
newVar->value = malloc(sizeof(char)*strlen(value));
should be
newVar->value = malloc(sizeof(char)*(strlen(value) + 1));
Since sizeof(char) is always 1
newVar->value = malloc(strlen(value) + 1);
could be used as well.
Another problem is in
// Reallocate size of subSections array
ini->subSections = realloc(ini->subSections, sizeof ( ini_t*) * (ini->subSectionsPtr+1));
// Set new subsection and enter it
newSection->prevSection = ini;
ini->subSections[ini->subSectionsPtr] = newSection;
ini->subSectionsPtr++;
ini = ini->subSections[ini->subSectionsPtr];
i++;
there is a reallocation of ini->subSections using (ini->subSectionsPtr+1) making ini->subSectionsPtr the last index for ini->subSections.
After ini->subSectionsPtr++, the index in one beyond the allocation.
Moving ini->subSectionsPtr++; down a line so it is just before i++; seems to fix this issue.
I have a struct named task. It's a linked list that contains a struct timing and a command. It's used to store the command I have to execute at a certain time:
// and here is the struct command:
struct argument {
size_t length; // length of the data string
char *data;
};
typedef struct argument argument;
struct command {
int argc; // amount of arguments(words) in argv
argument *argv; // here I already tried put argument **argv
};
typedef struct command command;
I initialize the task with task *this_task = malloc(sizeof(task));
and initialize the command with command *cmds = malloc(sizeof(command)).
I add the commands with this method:
command *addToCommand(command *cmd, size_t argSize, char *arg) {
argument *currentArgument = malloc(sizeof(argument) + argSize * sizeof(char));
if (currentArgument == NULL) {
cmd = NULL;
return cmd;
}
currentArgument->length = argSize;
currentArgument->data = arg;
if (cmd == NULL) {
cmd = malloc(sizeof(command));
if (cmd == NULL) return cmd;
cmd->argv = malloc(sizeof(argument));
cmd->argv[0] = *currentArgument;
cmd->argc = 1;
} else {
cmd->argc++;
cmd->argv = realloc(cmd->argv, (cmd->argc) * sizeof(argument));
cmd->argv[cmd->argc-1] = *currentArgument;
}
return cmd;
}
and then set it with this_task->cmd = cmds;
Now the problem: just after I did all this I printed the first argv of my task with printf( "%s\n", this_task->cmd->argv[0].data), and it showed 'test-0' like it should.
But the moment when I send it to an another method, like addTask(this_task), and print it again on the first line of the addTask method it shows weird symbols like "p<a�".
For example for this code :
void addTask(task *task_to_add) {
printf("arg inside addTask = '%s'\n", task_to_add->cmd->argv[0].data);
// i'm doing things here but even when everything is commented the bug happen
}
printf("arg before addTask = '%s'\n", this_task->cmd->argv[0].data);
addTask(this_task);
printf("arg after addTask = '%s'\n", this_task->cmd->argv[0].data);
Shows:
arg before addTask = 'test-0'
arg inside addTask = '`��'
arg after addTask = '`��'
In this project, I'm writing the command to a pipe, and reading it in the code above. While trying to make a minimal reproducible example, I noticed that when I remove the part reading from pipes and directly force the value for "test-0", it works correctly. So does the problem happen because of the way I'm reading the pipes? I also tried the solution of the "possible duplicate," but it didn't work. The issue is probably from how I read from the pipe.
I also noticed that if I don't have any other printf before the one displaying "arg before addTask ...", the arg before show " ", I commented it and wrote "THIS PRINTF" near it
How I compile and run:
gcc src/saturnd.c -o saturnd
gcc src/cassini.c -o cassini
./saturnd
./cassini (in another terminal)
The code who's reading the pipe:
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <stdint.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <unistd.h>
#include <endian.h>
struct argument {
size_t length;
char *data;
};
typedef struct argument argument;
struct command {
int argc;
argument *argv;
};
typedef struct command command;
struct task {
int id;
struct timing *timing;
command *cmd;
struct task *next;
};
typedef struct task task;
struct timing {
uint64_t minutes;
uint32_t hours;
uint8_t daysofweek;
};
int readHere;
task *tasks = NULL;
command *addToCommand(command *cmd, size_t argSize, char *arg) {
// printf("adding to cmd %s\n", arg);
argument *currentArgument = malloc(sizeof(argument) + argSize * sizeof(char));
if (currentArgument == NULL) {
cmd = NULL;
return cmd;
}
currentArgument->length = argSize;
currentArgument->data = arg;
if (cmd == NULL) {
cmd = malloc(sizeof(command));
if (cmd == NULL) return cmd;
cmd->argv = malloc(sizeof(argument));
cmd->argv[0] = *currentArgument;
cmd->argc = 1;
} else {
cmd->argc++;
cmd->argv = realloc(cmd->argv, (cmd->argc) * sizeof(argument));
cmd->argv[cmd->argc - 1] = *currentArgument;
}
return cmd;
}
void addTask(task *task_to_add) {
printf("arg inside addTask = '%s'\n", task_to_add->cmd->argv[0].data);
}
int main() {
char *readHere_path = "saturndReadPipe";
mkfifo(readHere_path, S_IRWXU | S_IRWXG | S_IRWXO);
readHere = open(readHere_path, O_RDONLY);
task *this_task = malloc(sizeof(task));
this_task->id = 0;
struct timing *reply_time = malloc(sizeof(struct timing));
reply_time->minutes = 5; // test vars
reply_time->hours = 5; // test vars
reply_time->daysofweek = 5; // test vars
uint32_t reply_argc;
read(readHere, &reply_argc, sizeof(reply_argc));
reply_argc = be32toh(reply_argc);
// reply_argc should be 2, because we wrote only 2 words "echo" and "test-0"
command *cmds = NULL;
for (int j = 0; j < (int) reply_argc; j++) {
uint32_t argSize_uint;
read(readHere, &argSize_uint, sizeof(argSize_uint));
int argSize = be32toh(argSize_uint);
int newSize = argSize + 1;
char arg[newSize];
int data_read = (int) read(readHere, &arg, argSize);
arg[data_read] = '\0';
//printf("read '%s' from pipe\n", arg); // THIS PRINTF
cmds = addToCommand(cmds, newSize, arg);
}
this_task->cmd = cmds;
this_task->next = NULL;
printf("arg before addTask = '%s'\n", this_task->cmd->argv[0].data);
addTask(this_task);
printf("arg after addTask = '%s'\n", this_task->cmd->argv[0].data);
exit(0);
}
The code which is writing in the pipe:
#include <stdlib.h>
#include <stdint.h>
#include <fcntl.h>
#include <unistd.h>
#include <endian.h>
int main() {
char *writeHere_path = "saturndReadPipe";
int writeHere = open(writeHere_path, O_WRONLY | O_TRUNC);
uint32_t cmd_argc = htobe32(2);
write(writeHere, &cmd_argc, sizeof(cmd_argc));
// sending "echo"
uint32_t length = htobe32(4);
write(writeHere, &length, sizeof(length));
char *cmd_data = "echo";
uint8_t d[4];
int j = 0;
for (; j < 4; ++j)
d[j] = cmd_data[j];
write(writeHere, &d, sizeof(d));
// sending "test-0"
length = htobe32(4);
write(writeHere, &length, sizeof(length));
cmd_data = "test-0";
uint8_t dd[4];
j = 0;
for (; j < 4; ++j)
dd[j] = cmd_data[j];
write(writeHere, &dd, sizeof(dd));
exit(0);
}
You do not copy string only assign the pointer to it. I would do it a bit different way.
typedef struct argument {
size_t length; // length of the data string
char data[];
}argument;
typedef struct command {
int argc; // amount of arguments(words) in argv
argument *argv[];
}command;
command *addToCommand(command *cmd, const size_t argSize, const char *restrict arg)
{
int newargc = cmd ? cmd -> argc + 1 : 1;
argument *currentArgument = malloc(sizeof(*currentArgument) +
(argSize + 1) * sizeof(currentArgument -> data[0])); //if argsize includes null terminating character remove "+1"
if (currentArgument)
{
currentArgument->length = argSize;
strcpy(currentArgument->data, arg);
cmd = realloc(cmd, sizeof(*cmd) + newargc * sizeof(cmd -> argv[0]));
if(cmd)
{
cmd -> argc = newargc;
cmd -> argv[newargc -1] = currentArgument;
}
}
return cmd;
}
I am asked to implement a reduced system shell that needs to be coded in C, and I have to achieve some of the features of an UNIX shell.
One of them is the replacement of ~[USER] to USER home dir, if USER appears, or the default environment variable "HOME" if it doesn't. I could write the code that iterates all over the commands (i.e. "ls ~hxshfx | sort | echo $var" -> argvv = {ls ~hxshfx, sort, echo $var}, but I can't figure out what to code if I want to change the own argvv value (i.e, ls /home/hxshfx | sort | echo a). I know I should use realloc but I don't understand how to use it when no malloc has been called. I do have another if statement for variables like $VAR but the problem is the same, the reallocation of information at argvv[i][j] position.
This is my code snippet:
void metacharacters (char *** argvv) {
int i, j;
char user, var, * aux, * toSubstitute, * name;
user = '~';
var = '$';
for (i = 0; argvv[i] != NULL; i++) {
for (j = 0; (aux = argvv[i][j]) != NULL; j++) {
if (aux[0] == user) {
struct passwd * pswd;
if (strlen(aux) > 1) {
name = (char *) struct passwd * pswd;malloc(sizeof(char) * (strlen(aux)-1));
strncpy(name, aux + 1, strlen(aux)-1);
pswd = getpwnam(name);
toSubstitute = pswd -> pw_dir;
free(name);
} else {
toSubstitute = getenv("HOME");
}
// TODO changes to argvv[i][j]
} else if (aux[0] == var) {
name = (char *) malloc(sizeof(char) * (strlen(aux)-1));
strncpy(name, aux + 1, strlen(aux)-1);
toSubstitute = getenv(name);
// TODO changes to argvv[i][j]
free(name);
}
}
}
}
The other thing I don't know how to solve is the shell function "set". When the shell recieves, i.e., "set myvar 1" it should use putenv to set the environment variable "myvar". I do think my function used to set the variable works okay:
void setVariable (char * arg1, char * arg2) {
int ret;
char * command = strdup(arg1);
strcat(command, "=");
strcat(command, arg2);
// i.e., at this point, command = "myvar=1", since arg1 = myvar; arg2 = 1
ret = putenv(command);
if (ret < 0) {
perror("putenv");
exit(1);
}
printf("%s=%s\n", arg1, getenv(arg1));
// I do think it works because getenv(arg1) works fine
free(command);
}
But, in the next iteration (or just outside the function setVariable), if I check what is the value of the environment variable "myvar", I always got null, no matter what. Also, if I print all the environment variables, there is no entry with "myvar" name, which is strange since, in the setVariable function, I had getenv(name) and that goes OK.
Thank you.
qq4all.
I have a task - write config parser for syntax like this:
[module]
name = first
imitationType = first
[module]
name = second
imitationType = second
etc.
I found pretty config parser - inih, but I can't force it to work as I want. Here my code, writed over inih example:
typedef struct {
const char* name;
const char* imitation_type;
} module_config;
int module_count = 0;
static int handler(void* user, const char* section, const char* name,
const char* value)
{
module_config* pconfig = (module_config*)user;
pconfig = (module_config *) malloc(module_count*sizeof(module_config));
#define MATCH(s, n) strcmp(section, s) == 0 && strcmp(name, n) == 0
if (strcmp(section, "module") == 0) {
if (MATCH("module", "name")) {
pconfig[module_count]->version = strdup(value);
} else if (MATCH("module", "imitationType")) {
pconfig[module_count]->name = strdup(value);
} else {
return 0; /* unknown section/name, error */
}
++module_count;
pconfig = (module_config *) realloc(pconfig, module_count * sizeof(module_config));
}
return 1;
}
But, when I trying to compile this, I get next error:
Error! Expression for '->' must be 'pointer to struct or union'
for those lines:
pconfig[module_count]->version = strdup(value);
pconfig[module_count]->name = strdup(value);
I'm newbie in programming, and don't understand, why this happens. Please, help :-)
pconfig is a pointer to an instance of the module_config struct.
Using pconfig[module_count] on this pointer is equivalent to dereferencing the pointer (pconfig+module_count), i.e. it is equivalent to *(pconfig+module_count).
Thus, pconfig[module_count] is no longer a pointer. You need to use pconfig[module_count].version or (pconfig+module_count)->version.
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.