Store getcwd on a struct on a function - c

typedef struct
{
char Path[100];
} DirectoryInformation;
void Getskelutofdirectorie(char * dir, int lvl)
{
DirectoryInformation DI[100];
char cwd[1024];
//Search recursive
// where I want to put the path on the struct to use on main
getcwd(cwd, sizeof(cwd));
strcpy(DI[0].Path, cwd);
}
int main(void)
{
DirecoryInformation DI[100];
printf("%s", DI[0].Path);
}
I can print the path but if i use on main function will work.
Can somebody help me out?
It executes without error but when I print out make segmentation fault

Your code invokes undefined behavior by using value of variable DI having automatic storage duration and not initialized, which is indeterminate.
Call the function with passing pointer to the struct to store the data, then store there.
typedef struct
{
char Path[100];
} DirectoryInformation;
void Getskelutofdirectorie(DirectoryInformation * DI, char * dir, int lvl)
{
char cwd[100]; // cwd was too long, so there was risk of buffer overrun when copying
//Search recursive
//where i want to put the path on the struct to use on main
getcwd(cwd, sizeof(cwd));
strcpy(DI[0].Path, cwd);
}
int main(void)
{
DirectoryInformation DI[100] = {{""}}; // initialize for in case the function fails to set values
Getskelutofdirectorie(DI, NULL, 0); // pass proper parameter
printf("%s", DI[0].Path);
}

Related

Write char to struct in C

Basically I have a struct which stores my general program settings. I read in a config with the callback function to get the corresponding value, but I can't write it to the struct. I've tried everything from memcpy over strcpy to dereferencing the char pointer, but every time the char in the struct stays empty. The passed string contains only one char, I checked that multiple times. Also if I strcpy a string to the other fields of the struct, it works fine.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct {
char *datafile;
char *logfile;
char mode;
} general_settings;
void setSettingsData(void){
log_trace("parsing config file for general settings initialisation");
config_error_t rc = config_parse("config.ini", handle_settings_ini_file);
if (rc != CONFIG_ERROR_NONE) {
log_error("Error parsing configuration: %s on line %lu", config_get_error_string(rc), config_get_line_number());
} else {
log_info("Settings parsed successfully!");
}
}
static config_error_t handle_settings_ini_file(char *section, char *key, char *value) {
if(section != NULL && !strcmp("Allgemein", section)) {
if (!strcmp("mode", key)) {
general_settings.mode = strdup(value); // ??????
log_info("Program Execution mode set to %s", value);
} else {
log_fatal("Unrecognized setting. Check for typos. Exiting...");
exit(0);
}
}
return CONFIG_ERROR_NONE;
}
Since value is a char *, you can get the char it points to with *value.
So you want general_settings.mode = *value;.
You could also use general_settings.mode = value[0];
Since a[b] is the same as *(a+b), *(value + 0) is the same as value[0] and also the same as *value.

Unwanted pointers modification

Situation: I'm currently working with chained lists and I am adding new elements through a function called inputRegistering(). I am positive that at the end of this function, an element have been added to the correct place.
Issue1: The added element modifies all the other to take its value.
Issue2: When exiting the function, and calling the inputReadingAll() function (which displays the list in its entirety), the elements are now all "empty", or replaced with gibberish (as can do the pointers).
Test1: I have tested to do a manual adding in the main() function and it seems everything worked fine. I can't understand what is the fundamental difference with my code though...
Code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAXLEN 256
typedef struct
{
struct elt *first;
struct elt *last;
} Tfile;
typedef struct elt
{
char *val;
struct elt *next;
} Telt;
int fileAdd(Tfile *, char *);
void fileInit(Tfile *);
void inputReadingAll(Tfile *);
void inputRegistering(Tfile *);
int main(int argc, char **argv){
Tfile file;
fileInit(&file);
inputRegistering(&file);
inputRegistering(&file);
inputReadingAll(&file);
}
int fileAdd(Tfile *F, char *newVal){
Telt *newElt;
newElt = (Telt*)malloc(sizeof(Telt));
if(newElt == NULL){
printf("Error\n");
return 0;
}
newElt->val = newVal;
newElt->next = NULL;
if(fileTaille(F) == 0)
F->first = newElt;
else
F->last->next= newElt;
F->last = newElt;
return 1;
}
void fileInit(Tfile *F){
F->first = NULL;
F->last = NULL;
}
void inputReadingAll(Tfile *file){
printf("> Reading all function\nBEGIN\n");
Telt *currElt = file->first;
while(currElt != NULL){
printf("%p, %s\n", currElt, currElt->val);
currElt = currElt->next;
}
printf("END\n");
}
void inputRegistering(Tfile *file){
printf("> Registering function\n> What to register : \n> ");
char temp[MAXLEN];
fgets(temp, MAXLEN, stdin);
temp[strcspn(temp, "\n")] = 0;
printf("Registering %s\n", temp);
fileAdd(file, temp);
}
The (pointer to) local array temp of the function inputRegistering() is passed to the function fileAdd() and the pointer is directly stored to the structure.
This is bad because the array is local and it is invalidated on returning from the function inputRegistering().
Instead of this, the function fileAdd() should copy the passed string and store the pointer to the copy in the structure.
This can be done like this:
newElt->val = malloc(strlen(newVal) + 1); /* +1 for terminating null-character */
if (newElt->val == NULL) {
printf("Error\n");
free(newElt);
return 0;
}
strcpy(newElt->val, newVal);
instead of this:
newElt->val = newVal;

strcpy() and char

I want to store a string to a char array inside a structure and when I access the char array I want the result to be displayed along with the value from the global variable errCode. When I access the errDesc member of the structure then I want the result to be "Error detected with error code 0xA0B0C0D0", but since using strcpy copies the string as it is I am getting a result "Error detected with error code %08lx" . Here is a sample code which replicates my issue:
int errCode = 0xA0B0C0D0;
void function(errpacket* ptr, int a, char* errString, ...);
typedef struct{
int err;
char errDesc;
}errpacket;
int main(){
errpacket* a;
void function(a, 10, "Error detected with error code %08lx", errCode);
return 0;
}
void function(errpacket* ptr, int a, char* errString, ...){
ptr->err = a;
strcpy(&ptr->errDesc, errString);
}
If my implementation is incorrect, please suggest me a way to do what I intend to. Also please point out the mistakes in the above code.
you have to typedef the struct errpacket before declaration of function(...)
Variable a in function main() is only a pointer. You'll get a segmentation fault inside function if you try to write to an uninitialized pointer.
The member errDesc will only hold ONE char, not a string or char array.
Try this...
int errCode = 0xA0B0C0D0;
typedef struct {
int err;
char* errDesc;
} errpacket;
void function (errpacket* ptr, int a, char* errString, ...);
int main () {
errpacket a;
function(&a, 10, "Error detected with error code %08lx", errCode);
return 0;
}
void function (errpacket* ptr, int a, char* errString, ...) {
ptr->err = a;
ptr->errDesc = strdup( errString);
}
try this fix:
#include <stdarg.h> //to be added for vsprintf use
int errCode = 0xA0B0C0D0;
void function(errpacket* ptr, int a, char* errString, ...);
typedef struct{
int err;
char *errDesc;
}errpacket;
int main(){
errpacket a; //you need allocate memory if you use a pointer here
void function(&a, 10, "Error detected with error code %08lx", errCode);
return 0;
}
void function(errpacket* ptr, int a, char* errString, ...){
ptr->err = a;
ptr->errDesc = malloc(strlen(errString)+1);
memset(ptr->errDesc, 0, strlen(errString)+1);
/*if(ptr->errDesc != NULL)
{
strcpy(ptr->errDesc, errString);
}*/
// use like following if you want use a formatted string
if(ptr->errDesc != NULL)
{
va_list args;
va_start (args, errString);
vsprintf (ptr->errDesc, errString, args);
va_end (args);
}
}
You can't use a single char variable to hold an entire string.
What you can do is declare errDesc to be either an array of fixed length (if you know the maximum number of characters that an error description can contain), or a pointer that is allocated dynamically with malloc and later freed with free.
Array case:
#define MAX_ERR_STRING_SIZE 500
typedef struct
{
int err;
char errDesc[MAX_ERR_STRING_SIZE];
} errpacket;
// You can now use strcpy() to copy to errpacket::errDesc assuming none of the error strings exceed MAX_ERR_STRING_SIZE
Dynamic memory:
typedef struct
{
int err;
char *errDesc;
} errpacket;
// Take note of the new parameter: int errStringLength,
void function(errpacket* ptr, int a, char* errString, int errStringLength, ...){
ptr->err = a;
ptr->errDesc = malloc((errStringLength + 1) * sizeof(char));
if(ptr->errDesc == NULL)
{
perror("malloc");
exit(EXIT_FAILURE);
}
strcpy(&ptr->errDesc, errString);
}
After you are done using ptr you will need to call free(ptr->errDesc); to de-allocate the string.
I don't think you really want a function with variable arguments, like printf. The solution below just expects the arguments you use in the end. Note that I do not use a user-supplied format string; that is considered a security risk. I also used snprintf (instead of the simple sprintf) in order to protect against error messages which are longer than the array size in the struct. The array size is a define so that it can be changed easily.
Specific fixes:
Proper declaration order (define the struct type before it's used)
Define an actual error packet object (and not just an uninitialized pointer to one)
Provide actual memory in the error packet for the message
Provide a print function for error packets
Do not let the user code specify printf formats; print user supplied strings with a length protected %s format specifier.
Do not use a variable argument function (whose excess arguments were not evaluated anyway); just declare the needed arguments explicitly.
.
#include<stdio.h>
int errCode = 0xA0B0C0D0;
#define MAX_ERRDESC_LEN 80 // avoid literals
typedef struct{
int err;
char errDesc[MAX_ERRDESC_LEN]; // provide actual space for the message
}errpacket;
void printErrPack(FILE *f, errpacket *ep){
fprintf(f, "Error packet:\n");
fprintf(f, " err = 0x%x:\n", ep->err);
fprintf(f, " desc = ->%s<-\n", ep->errDesc);
}
// Standard function with fixed argument count and types
void function(errpacket* ptr, int errNo, char* errString, int errCodeArg){
ptr->err = errNo;
// snprintf "prints" into a string
snprintf( ptr->errDesc, // print destination
MAX_ERRDESC_LEN, // max length, no buffer overflow
"%s with error code %x", // do not use user string as format
errString, // user supplied string, printed via %s
errCodeArg );
}
int main(){
errpacket a; // define an actual object, not a pointer
// pass the address of the object a
function(&a, 0xdead, "Error detected ", errCode);
printErrPack(stdout, &a);
return 0;
}

search a struct in C

void search(struct _data *BlackBox, char *name, int size) - this function
will get the dynamic array of struct passed to it, the name we are looking
for, and the size of the array. This function will then search the dynamic
array for the name.
typedef struct _data
{
char* name;
long number;
} _data;
int scan(FILE *(*stream));
struct _data *load(FILE *stream, int size);
void search(struct _data *Blackbox, char *name, int size);
int main()
{
int size = scan(&stream);
rewind(stream);
_data *data = load(stream, size);
char input;
printf("Please Input Search Name: ");
scanf("%s", input);
while (input != NULL)
{
search(data, input, size);
}
}
void search(struct _data *Blackbox, char *name, int size)
{
for (int i=0; i<size; i++)
{
if (strcmp(name,Blackbox[i].name) != 0)
{
printf("Success");
}
else
{
printf("Name Not Found");
}
}
}
But I am getting the following output
Output:
LINES: 2
ron 7774013
jon 7774014
Please Input Search Name: ron
RUN FINISHED; Segmentation fault: 11; real time: 2s; user: 0ms; system: 0ms
In your main function you have "char input;", and "scanf("%s",input);". That's wrong, because the %s specifies a string parameter, but input is a char variable. So whatever is typed in by the user is stored at some random place in memory.
Change the declaration of input to something lime "char input[1000];". And you'll have to do something about your while loop too.
You need to declare the search function before you try to use it.
The compiler should even warn you about that implicit declaration.
If you get a segmentation fault then one the following applies:
Your struct Blackbox in search function is not pointing to a valid memory location and thus the Blackbox[i] produces the fault
The name member of the struct is not pointing to a valid memory location and thus the Blackbox[i].name is producing the fault
The size of the Blackbox array is less than size-1.
To do this, use a debugger and check the Blackbox where is pointing. Then check the Blackbox.name where is pointing. Then, check if there is anything to the Blackbox array up to size-1. I assume that either will be null. Perhaps an error in the assignment of the load function or a wrong usage of the size.

C Function pointer parameter not the same when function exits

I am having a problem with passing a pointer to a function. When the function returns the pointer seems to be different than what it is in the function.
So I pass a pointer to the function which gets raw image data which should then be stored in the memory referenced by the pointer.
If I then pass the pointer from inside the raw image function to a function to create a JPEG file from the raw data then it works correctly.
If I first wait for the raw image function to finish and then call the JPEG function using the pointer I passed to the raw image function then it fails to create the image.
A simplified version of the code is below:
int getRawImage(unsigned char *pBuffer);
int writeJPEGBFile(unsigned char *idata, char *ofile);
int main(int argc, char** argv) {
unsigned char *rawData = NULL;
char filename[MAXPATHLEN] = "/home/user/tst/img.jpg";
getRawImage(rawData);
// This does not work
writeJPEGBFile(rawData, filename);
free(rawData);
return 0;
}
int getRawImage(unsigned char *pBuffer) {
void *hDevice;
hDevice = scanOpenDevice();
// Removed code for simplification
scanGetFrame(hDevice, pBuffer, NULL)
scanCloseDevice(hDevice);
// This Works!!
//char filename[MAXPATHLEN] = "/home/user/tst/img.jpg";
//writeJPEGBFile(pBuffer, filename);
return 0;
}
int writeJPEGBFile(unsigned char *idata, char *ofile) {
// JPEG code goes here
return 0;
}
My question is what am I doing wrong and how can I pass the rawData pointer to the writeJPEGBFile() function successfully in the main() function?
The definition for scanGetFrame() is as follows:
typedef void *FTR_PVOID;
FTR_API_PREFIX FTR_BOOL FTR_API ftrScanGetFrame( FTRHANDLE ftrHandle, FTR_PVOID pBuffer, PFTRSCAN_FRAME_PARAMETERS pFrameParameters );
The scanGetFrame() function comes from a 3rd party library that I am linking with so I will not be able to change the definition.
Given that rawData is a null pointer in main(), you almost certainly need to revise the interface to getRawImage() so that it takes a char ** and you pass &rawData to it. You also need to think about how the calling code will know how big the data is.
I managed to work it out. Thanks to all for the pointers which led me to the solution:
int getRawImage(unsigned char *pBuffer);
int writeJPEGBFile(unsigned char *idata, char *ofile);
int main(int argc, char** argv) {
unsigned char *rawData; // Removed the NULL assignment
char filename[MAXPATHLEN] = "/home/user/tst/img.jpg";
// Set the size of rawData - loadImageSize() sets the value of the ImageSize class variable.
loadImageSize();
rawData = (unsigned char *) malloc(ImageSize.nImageSize);
getRawImage(rawData);
// This works now
writeJPEGBFile(rawData, filename);
free(rawData);
return 0;
}
int getRawImage(unsigned char *pBuffer) {
void *hDevice;
hDevice = scanOpenDevice();
// Removed code for simplification
scanGetFrame(hDevice, pBuffer, NULL)
scanCloseDevice(hDevice);
return 0;
}
int writeJPEGBFile(unsigned char *idata, char *ofile) {
// JPEG code goes here
return 0;
}

Resources