I don't understand how the freeing is working. I know this happens when I try to free memory twice. However, this is really stumping me.
I've tried to post just the relevant parts of the code.
FILE* file = fopen(path, "r");
if (file == NULL)
{
error(500);
return;
}
// load file's content
BYTE* content;
size_t length;
if (load(file, &content, &length) == false)
{
error(500);
return;
}
This is the load fucntion
bool load(FILE* file, BYTE** content, size_t* length)
{
printf("\nLOAD STARTED\n");
content = NULL;
BYTE *data = NULL;
int size = 0;
while(!feof(file))
{
char ch = fgetc(file);
size += 1;
data = realloc(data, sizeof(BYTE) * (size));
*(data + (size - 1)) = ch;
}
content = &data;
*length = size;
printf("\nLOAD ENDED\n");
return true;
}
A little while later I'm calling free()
printf("\nFREEING CONTENT\n");
// free file's content
free(content);
printf("\nCONTENT FREED\n");
The printf statement FREEING CONTENT works after which I get the
munmap_chunk(): invalid pointer error.
This is the problem:
content = &data;
It assigns the address of a local variable that goes out of scope after the function returns. Since content is a function parameter, nothing gets written to where it points. Did you mean to write
*content = data;
instead? If so you, you should not set content = NULL because you want to use the address passed by the call load(file, &content, &length).
I managed to fix it.
content was basically just a char*. So, I tried this and it worked...
I changed content = &data to content = &(data[0])
It works. Appreciate all the inputs. :D
Related
When ever I try to access data in memory that I've acquired using malloc, the data is corrupted
I'm writing a program that reads Linux directories and writes the names of the files and sub-directories in a "string array" (char** array in c). It operates using dirent.h functionalities like readdir(). readdir returns a dirent structure that has a dname[256] that's the name of a file/sub-directory in the target directory. I equate the dirent string(char*) to an index of a malloced position in a char** array
I basically have a walk_path() function that reads the directory entries and writes their names into a malloced location then return that location
data_t* walk_path(char* path) {
int size = 0;
if(path == NULL){
printf("NULL path\n");
return NULL;
}
struct dirent* entry;
DIR* dir_l = opendir(path);
if(dir_l == NULL) {
char** data = (char**)malloc(sizeof(char*) * 2);
data[0] = path;
data_t* ret = (data_t*)malloc(sizeof(data_t));
ret->data = data;
ret->size = 1;
return ret;
}
while((entry = readdir(dir_l)) != NULL) {
if(!strcmp(entry->d_name, ".") || !strcmp(entry->d_name, ".."))
continue;
size++;
}
closedir(dir_l);
char** data = (char**)malloc(sizeof(char*) * size + 1);
int loop_v = 0;
dir_l = opendir(path);
while((entry = readdir(dir_l)) != NULL && loop_v < size) {
if(!strcmp(entry->d_name, ".") || !strcmp(entry->d_name, ".."))
continue;
data[loop_v] = entry->d_name;
loop_v++;
}
closedir(dir_l);
data_t* ret = (data_t*)malloc(sizeof(data_t*));
ret->size = (size_t)size;
ret->data = data;
return ret;
}
and a merge path function that can take two directories and write their data into a single array
char** merge_path(char* path, char* path2) {
data_t* path_data = walk_path(path);
data_t* path2_data = walk_path(path2);
if(path_data == NULL || path2_data == NULL) {
printf("Merge failed, couldn't get path data\n");
return NULL;
}
char** new_dir_info = (char**)malloc(sizeof(char*) * (path2_data->size + path_data->size) );
if(new_dir_info == NULL)
return NULL;
int loop = 0;
while(loop < path_data->size) {
new_dir_info[loop] = path_data->data[loop];
loop++;
}
loop = 0;
while(loop < path2_data->size) {
new_dir_info[loop + path_data->size] = path2_data->data[loop];
loop++;
}
free(path_data);
free(path2_data);
return new_dir_info;
}
The char** array that the merge path function returns always has corrupted data, that is the characters in the character arrays are corrupted and not the pointers themselves, though I expect it to have the strings passed to it from the directory entries it instead has random strings.
I've stepped through the code and found that the data gets corrupted in merge path function, the source of the error could still originate from walk_path().
This
data_t* ret = (data_t*)malloc(sizeof(data_t*));
ought to be
data_t* ret = (data_t*)malloc(sizeof(data_t));
Generally in C void-pointers do not need to be casted, so all casts to malloc in your code can be dropped, which made the above line look like:
data_t* ret = malloc(sizeof(data_t*));
More over to rule out bugs like this one better step away from doubling the type to mallocate inside the call to malloc(), but better use the variable to allocate to along with the dereferencing operator, like this:
data_t* ret = malloc(sizeof *ret);
Also this line
data[loop_v] = entry->d_name;
copies a pointer to the entry name, not the name itself.
Consider using
data[loop_v] = strdup(entry->d_name);
which dynamically allocates room for a copy of where entry->d_name points to.
Alternatively instead of
char**data;
define
char (*data)[sizeof entry->d_name]; /* Array of pointers to char[as many char as entry->d_name is defined to have] */
or
char (*data)[sizeof ((struct dirent*)NULL)->d_name]; /* Array of pointers to char[as many char as entry->d_name is defined to have] */
and allocate to it like this (following the above proposed pattern):
data = malloc((size /* + 1 */) * sizeof *data); /* Not sure what the idea behind this +1 is. */
And instead of
data[loop_v] = strdup(entry->d_name);
do
strcpy(data[loop_v], entry->d_name);
If going this route you need to adjust the definition of data_t.data accordingly.
I've been trying to fix this for 2 days now. I really don't understand what is going on.
I wrote a function to read from a file line per line. It's called get_next_line(). This is a project for school, I'm only allowed to use my own C library and read(), malloc() and free().
Here is a link to the full GitHub repo, including the instructions. I can only submit get_next_line.c and get_next_line.h at the end.
Basically, my program seems to run fine if don't handle memory leaks. When I start fixing leaks by using my ft_strdel() function, my program still runs fine for most test cases.
void ft_strdel(char **as)
{
if (!as || !*as)
return ;
free(*as);
*as = 0;
}
Yet, if I pass it through the advanced unit test we have at school, I have different errors. They seem to appear randomly sometimes as I can pass 3 times in a row and get a malloc error the 4th time.
The current version seems to handle all memory leaks. Thus, I have this error from the filechecker:
get_next_line_tests(43165,0x7fff9e83d340) malloc: *
error for object 0x7fe0e3403748: incorrect checksum for freed object -
object was probably modified after being freed.
* set a breakpoint in malloc_error_break to debug
Here is the full function:
#include "get_next_line.h"
static t_list *get_current_node(const int fd, t_list **line_list)
{
t_list *tmp;
tmp = *line_list;
while (tmp)
{
if ((int)tmp->content_size == fd)
return (tmp);
tmp = tmp->next;
}
return (NULL);
}
static t_list *create_new_node(int fd, t_list **line_list)
{
t_list *new;
new = ft_lstnew("\0", fd);
ft_lstadd(line_list, new);
return (new);
}
char *read_until_newline(int fd)
{
char buf[BUFF_SIZE + 1];
char *tmp;
char *stack;
int ret;
if (read(fd, buf, 0) < 0)
return (NULL);
stack = ft_strnew(1);
if (!stack)
return (NULL);
while ((ret = read(fd, buf, BUFF_SIZE)) > 0)
{
buf[ret] = '\0';
tmp = ft_strjoin(stack, buf);
ft_strdel(&stack);
stack = tmp;
if (ft_strchr(buf, '\n'))
break;
}
return (stack);
}
int get_index_newline(char *str)
{
int i;
i = 0;
while (str[i] && str[i] != '\n')
i++;
return (i);
}
int get_next_line(const int fd, char **line)
{
static t_list *line_list;
t_list *current;
char *buffer;
char *tmp;
int index_newline;
if (fd < 0 || line == NULL)
return (-1);
current = get_current_node(fd, &line_list);
if (!current)
current = create_new_node(fd, &line_list);
if (!ft_strchr(current->content, '\n'))
buffer = read_until_newline(fd);
else
buffer = ft_strnew(1);
if (!buffer)
return (-1);
if (!ft_strlen(buffer) && !ft_strlen(current->content))
return (0);
tmp = current->content;
current->content = ft_strjoin(tmp, buffer);
if (tmp)
ft_strdel(&tmp);
if (buffer)
ft_strdel(&buffer);
index_newline = get_index_newline(current->content);
*line = ft_strsub(current->content, 0, index_newline);
tmp = current->content;
current->content = ft_strsub(tmp, index_newline + 1, ft_strlen(tmp) - index_newline - 1);
if (tmp)
ft_strdel(&tmp);
return (1);
}
Feel free to comment on any beginner error I could be doing in my code. Please note however that I have to follow a certain norm, that explain my variable declarations and initializations. I cannot use for loops. And have many restrictions like those.
Protecting my ft_strdel() calls with if statements was my last attent at solving the issue, obviously it failed and it's useless.
EDIT:
I handle multiple fd by using a static linked list. Each node contains a string with the last read buffer (whatever is left from the reading after substracting the most recently read line). And each node contains an int to store the fd it was read from. This way, I loop through the list until I find the corresponding fd to check for preexisting reading. If no node is returned, it means I have nothing stored for the specific fd so I'll just create a new node.
I hope you have answers! I'm not a regular user on Stack Overflow, I did my best to format my post and be specific. Tell me if I need to edit something.
And thanks for your help!
I have a problem that I can't figure out. I have the following files: file_reader.c, file_reader.h, file_writer.c, file_writer.h, test_file_reader.c
I'm working with 'struct' to read and write files. For better understanding I wrote the following code test_file_reader.c:
#include <stdio.h>
#include "file_reader.h"
#include "file_writer.h"
int main ()
{
char *file_path = "/home/freitas/Dropbox/projects/gcleaner/cleaners/custom.xml";
struct FileReader *fr = malloc(sizeof(struct FileReader));
file_reader_new (file_path, fr);
show_file_reader_values(fr);
struct FileWriter *fw = malloc(sizeof(struct FileWriter));
fw->file_path = "/tmp/text1.txt";
fw->content = "aaa";
write (fw);
show_file_reader_values(fr);
return 0;
}
void show_file_reader_values(const struct FileReader *fr)
{
printf("==========FILE READER==========\n");
printf("file path: %s\n", fr->file_path);
printf("----------file content---------\n");
printf("content:\n%s\n", fr->content);
printf("----------file content---------\n");
printf("n lines: %d\n", fr->n_lines);
printf("n characters: %d\n", fr->n_characters);
printf("==========FILE READER==========\n\n");
}
The function 'file_reader_new' reads the file and then signs the content, file path, number of lines and number of characters to the 'struct' 'FileReader'.
When I call the function 'show_file_reader_values' in the first time I do not have problems with the content but when I call the function 'write' and then call the function 'show_file_reader_values' again, the content is not the same anymore. The question is that the function 'write' of the file 'file_writer.c' and its struct does not have any relation to the file 'file_reader' and its struct. So, how can a function using another struct change the values of another struct of another file ?
The output:
[freitas#localhost test]$ ./test_file_reader
==========FILE READER==========
file path: /home/freitas/Dropbox/projects/gcleaner/cleaners/custom.xml
----------file content---------
content:
<cleaner> <id>k3b</id> <label>k3b</label> <description>Disc writing software</description> <option> <id>log</id> <label>Log</label> <description>Delete the log file which contains information about the last writing session(s).</description> <command>delete</command> <search>glob</search> <path>~/.kde/share/apps/k3b/*.log</path> </option> <option> <id>log2</id> <label>Log</label> <description>Delete the log file which contains information about the last writing session(s).</description> <command>delete</command> <search>glob</search> <path>~/.kde/share/apps/k3b/*.log</path> </option> </cleaner>
----------file content---------
n lines: 1
n characters: 621
==========FILE READER==========
==========FILE READER==========
file path: /home/freitas/Dropbox/projects/gcleaner/cleaners/custom.xml
----------file content---------
content:
<cleaner> <id>k��U�N
----------file content---------
n lines: 1
n characters: 621
==========FILE READER==========
Did you see ? In the first call I had the entire output:
<cleaner> <id>k3b</id> <label>k3b</label> <description>Disc wri...
but in the second call I had:
<cleaner> <id>k��U�N
file_reader.c
#include <stdio.h>
#include <stdlib.h>
#include "file_reader.h"
int file_reader_new(const char *file_path, struct FileReader *fr)
{
char *content; // holds the file content.
int counter; // holds the file number of lines.
size_t i; // indexing into content.
size_t buffer_size; // size of the content.
char *temp; // for realloc().
char c; // for reading from the input.
FILE *input; // our input stream.
if ((input = fopen(file_path, "r")) == NULL) {
fprintf(stderr, "Error opening input file %s\n", file_path);
exit(EXIT_FAILURE);
}
/* Initial allocation of content */
counter = 0;
i = 0;
buffer_size = BUFSIZ;
if ((content = malloc(buffer_size)) == NULL) {
fprintf(stderr, "Error allocating memory (before reading file).\n");
fclose(input);
}
while ((c = fgetc(input)) != EOF) {
/* Enlarge content if necessary. */
if (i == buffer_size) {
buffer_size += BUFSIZ;
if ((temp = realloc(content, buffer_size)) == NULL) {
fprintf(stderr, "Ran out of core while reading file.\n");
fclose(input);
free(content);
exit(EXIT_FAILURE);
}
content = temp;
}
/* Add input char to the content. */
content[i++] = c;
/* If the character is a break of line
* then the counter will be incremented.
*/
if (c == '\n')
counter++;
}
/* Test if loop terminated from error. */
if (ferror(input)) {
fprintf(stderr, "There was a file input error.\n");
free(content);
fclose(input);
exit(EXIT_FAILURE);
}
/* Make the content a bona-fide string. */
if (i == buffer_size) {
buffer_size += 1;
if ((temp = realloc(content, buffer_size)) == NULL) {
fprintf(stderr, "Ran out of core (and only needed one more byte too ;_;).\n");
fclose(input);
free(content);
exit(EXIT_FAILURE);
}
content = temp;
}
content[i] = '\0';
/* Assigns the variables to the corresponding
* element of the struct.
*/
fr->file_path = file_path;
fr->content = content;
fr->n_lines = counter;
fr->n_characters = i;
/* Clean up. */
free(content);
fclose(input);
return 0;
}
file_reader.h
#ifndef FILE_READER_H_
#define FILE_READER_H_
typedef struct FileReader
{
char *content; // holds the file content.
char *file_path; // holds the file path.
int *n_lines; // holds the number of lines.
int *n_characters; // holds the number of characters.
} FileReader;
// file_reader_new - reads the file
int file_reader_new(const char *file_path, struct FileReader *fr);
#endif
file_writer.c
#include <stdio.h>
#include "file_writer.h"
void write (struct FileWriter *fw)
{
FILE *f = fopen(fw->file_path, "w");
if (f == NULL)
{
printf("Error opening file!\n");
exit(1);
}
fprintf(f, "%s", fw->content);
fclose(f);
}
file_writer.h
#ifndef FILE_WRITER_H_
#define FILE_WRITER_H_
typedef struct FileWriter
{
char *file_path;
char *content;
int *error;
} FileWriter;
#endif
Can you help me ? Thanks!
struct FileReader *fr = malloc(sizeof(struct FileReader));
There is no need to do this. All you need is this:
struct FileReader fr;
Same here:
struct FileWriter fw;
Then just pass the address of these variables to the requisite function(s).
Note this was not given to you as an answer, only as a comment to clean up your code a bit to remove extraneous calls to the heap. It just so happens that the real problem exists elsewhere, and what you're seeing here is undefined behavior in full glory.
I am not sure how are you reading from the file, character by character or block, but anyhow ,
since you update the read data in content buffer, and store the address of content buffer inside file_reader_new() into variable fr->content and immediately releasing the memory will end up loosing the data you read. and lead to condition called Dangling pointer
Dangling pointer
( a pointer variable, which points to a released memory )
that's why its always advised to set the pointer variable after releasing to NULL. Dereferencing a dangling pointer is will lead to Segmentation fault or undefined behavior in some scenarios.
Also, since all you member variables of struct are pointers its better to initialize them to NULL.
you can use calloc to initialize all the variables in a struct, instead of malloc to initialize all the members to NULL, if you are going with dynamic allocation. which goes for string also.
Here is an issue that I see:
fr->content = content;
fr->n_lines = counter;
fr->n_characters = i;
/* Clean up. */
free(content); /* <-- Danger */
You do this in your file_reader_new function. You then call show_file_reader_values and in that function, you're accessing content:
printf("content:\n%s\n", fr->content);
Since you called free() on the content, that pointer no longer points to valid memory, thus undefined behavior occurs.
The fix is to allocate space on fr for the content and copy the characters of content to this space, or simply not call free on content.
So either do this:
fr->content = malloc(i + 1);
strcpy(fr->content, content);
fr->n_lines = counter;
fr->n_characters = i;
/* Clean up. */
free(content);
or this:
fr->content = content;
fr->n_lines = counter;
fr->n_characters = i;
/* No call to free(content) done */
So I have the following question:
I have this struct ListAut
struct ListAut{
char* biggestn;
int sizeof_biggestn;
int total_len;
struct node* avl;
};
Its typedef is as it follows:
typedef struct ListAut *IndexOfAuts;
IndexOfAuts *newIndexOfAuts()
{
int i;
IndexOfAuts *ioa = malloc(27 * sizeof(struct ListAut));
for (i = 0; i < 27; i++)
{
ioa[i]->biggestn = "";
ioa[i]->sizeof_biggestn = 0;
ioa[i]->total_len = 0;
ioa[i]->avl = NULL;
}
return ioa;
}
void insertName(IndexOfAuts * ioa, char *nome)
{
char *aux = malloc(sizeof(nome));
aux = trim(nome);
int index = getIndexOfLetter(aux);
if (nameLen(aux) > getSizeOfLongName(ioa[index]))
{
strcpy(ioa[index]->biggestn, aux);
ioa[index]->sizeof_biggestn = nameLen(aux);
}
ioa[index]->total_len += nameLen(aux);
insert(ioa[index]->avl, aux);
}
This is an important part of a module I need for a project, and on its main it's Seg Faulting. I suspect it's on the creation of an "object" newIndexOfAuts(),
The idea of this module is to have an array of 27 pointers to those structures, one to each letter and another to the special characters;
Now I'm just confused because it might be from the problem above or from a module loader I made:
void loadModules(char *filename, IndexOfAuts * ioa, StatTable st)
{
char *nameofile = malloc(20);
strcpy(nameofile, filename);
FILE *file = fopen(nameofile, "r");
if (file != NULL)
{
int counter, ano;
char *buff, *field, *auxil;
buff = malloc(1024);
field = malloc(200);
auxil = malloc(200);
while (fgets(buff, 1024, file))
{
counter = 0;
field = strtok(buff, ",");
printf("inserting 1st name\n");
insertName(ioa, field);
counter++;
while (!atoi(field))
{
if ((auxil = strtok(NULL, ",")) != NULL)
{
counter++;
field = auxil;
insertName(ioa, field);
}
}
ano = atoi(field);
incPub(st, ano, counter - 1);
}
fclose(file);
}
}
When i run this in main that has the following lines:
printf("Creating Stat Table");
StatTable st=newStatTable();\\This Line is correct, i checked it,i hope
printf("Creating index");
IndexOfAuts* ioa=newIndexOfAuts();
printf("Loading Modules");
loadModules(filename,ioa,st);
Those prints were for me to see where was the cause of the seg fault, but the last line printed was the "Creating Index".
There are several cases of undefined behavior and one memory leak (and a possible case of undefined behavior too):
You have this initialization ioa[i]->biggestn=""; It make the biggestn member point to a constant array of one character (the '\0' character). You then do strcpy(ioa[index]->biggestn,aux); which will write over a constant character, and then go outside of the array writing into unknown memory.
You have this: char* aux=malloc(sizeof(nome)); That allocates only 4 or 8 bytes, which the size of the pointer and not what the pointer points to. Use strlen to get the length of a string.
For the above allocation you also need to allocate a byte extra, as strlen only returns the length of the string without the terminator.
You have aux=trim(nome); This overwrites the pointer you just allocated, leading to a memory leak.
The above call might also lead to undefined behavior if you return a pointer to a local variable or array.
There are probably other problematic lines, these were just the ones I found on a quick glance.
And a general tip: Learn to use a debugger! The debugger is a programmers best tool next to the compiler. If you run your program in a debugger, the debugger will stop at the location of the crash, and let you examine (and also walk up) the function call stack, as well as let you examine values of variables.
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.