I have a litle probem with C programming. I have to write a programm for the university and I wrote the whole programm on my windows pc.
I tried it afterwards on a linux system and I got different output.
Here is the code:
char *compress(char *input,int lineSize)
{
int n = 0;
char *compr = (char*)malloc(lineSize * sizeof(char));
//compr++;
char c = *input;
while(*input != '\0')
{
printf("compr: %s\n",compr);
if(*input != c)
{
snprintf(compr,lineSize,"%s%c%d",compr,c,n);
n = 0;
c = *input;
n++;
}
else
{
n++;
}
input++;
}
snprintf(compr,lineSize,"%s%c%d%c",compr,c,n,'\0');
printf("compr: %s\n",compr);
return compr;
}
this works as it should on my windows pc, but when I run it on linux I get a file writing error + the "compr" array is empty :/
I hope anyone could help me, couldnt find any solution.
thanks
Compile with warnings:
warning: function returns address of local variable [enabled by default]
Another possible problem:
snprintf(compr,lineSize,"%s%c%d%c",compr,c,n,'\0');
From the sprintf man page:
Some programs imprudently rely on code such as the following
sprintf(buf, "%s some further text", buf);
to append text to buf. However, the standards explicitly note that the
results are undefined if source and destination buffers overlap when
calling sprintf(), snprintf(), vsprintf(), and vsnprintf(). Depending
on the version of gcc(1) used, and the compiler options employed,
calls such as the above will not produce the expected results.
Related
With the same command in my coworker's PC, my program works without the problem.
But in my PC, the program crashes with segfault;
GDB backtrace at core reads as follows:
#0 strrchr () at ../sysdeps/x86_64/strrchr.S:32
32 ../sysdeps/x86_64/strrchr.S: no such file or directory
(gdb) bt
#0 strrchr () at ../sysdeps/x86_64/strrchr.S:32
#1 0x00007f10961236d7 in dirname (path=0x324a47a0 <error: Cannot access memory at address 0x324a47a0>) at dirname.c:31
I'm already compiling the executable with -g -ggdb options.
Odd thing is that.. with valgrind the program works without error in my PC as well.
How can I solve the problem? I've observed that the errors occur only with strrchr, strcmp, strlen, ... string.h functions.
+Edit: the gdb backtrace indicates that the program crashes here:
char* base_dir = dirname(get_abs_name(test_dir));
where get_abs_name is defined as
char* get_abs_name(char* dir) {
char abs_path[PATH_MAX];
char* c = malloc(PATH_MAX*sizeof(char));
realpath(dir, abs_path);
strcpy(c, abs_path);
return c;
}
+Edit2: 'dir' is a path of certain file, like '../program/blabla.jpg'.
Using valgrind,
printf("%s\n", dir)
normally prints '/home/frozenca/path_to_program'.
I can't guess why the program crashes without valgrind..
We cannot know for sure without a Minimal, Complete, and Verifiable example. Your code looks mostly correct (albeit convoluted), except you do not check for errors.
char* get_abs_name(char* dir) {
char abs_path[PATH_MAX];
char* c = malloc(PATH_MAX*sizeof(char)); /* this may return NULL */
realpath(dir, abs_path); /* this may return NULL */
strcpy(c, abs_path);
return c;
}
Now, how could this lead to an error like you see? Well, if malloc returns NULL, you'll get a crash right away in strcpy. But if realpath fails:
The content of abs_path remains undefined.
So strcpy(c, abs_path) will copy undefined content. Which could lead to it copying just one byte if abs_path[0] happens to be \0. But could also lead to massive heap corruption. Which happens depends on unrelated conditions, such as how the program is compiled, and whether some debugging tool such as valgrind is attached.
TL;DR: get into the habit of checking every function that may fail.
char* get_abs_name(char* dir) {
char abs_path[PATH_MAX];
char* c = malloc(PATH_MAX*sizeof(char));
if (!c) { return NULL; }
if (!realpath(dir, abs_path)) {
free(c);
return NULL;
}
strcpy(c, abs_path);
return c;
}
Or, here, you can simplify it alot assuming a GNU system or POSIX.1-2008 system:
char * get_abs_name(const char * dir) {
return realpath(dir, NULL);
}
Note however that either way, in your main program, you also must check that get_abs_name() did not return NULL, otherwise dirname() will crash.
Drop your function entirely and use the return value of realpath(dir, NULL) instead.
Convert type
char* c = malloc(PATH_MAX*sizeof(char));
Thanks!
I have a C program, that I would like to print its output from swift, and when it scans I can give it input through Swift. Is such thing possible? I tried this with a simple function, and it worked, but how can someone do so with many different functions that call other functions?
I know the question is a bit vague, but can someone point me into the right direction?
Example of code:
int main(int argc, char **argv) {
int i;
int hitme;
char ch;
prelim();
if (argc > 1) { // look for -f option
if (strcmp(argv[1], "-f")== 0) {
coordfixed = 1;
argc--;
argv++;
}
}
if (argc > 1) {
fromcommandline = 1;
line[0] = '\0';
while (--argc > 0) {
strcat(line, *(++argv));
strcat(line, " ");
}
}
else fromcommandline = 0;
while (TRUE) { /* Play a game */
setup();
if (alldone) {
score(0);
alldone = 0;
}
else makemoves();
skip(2);
stars();
skip(1);
if (tourn && alldone) {
printf("Do you want your score recorded?");
if (ja()) {
chew2();
freeze(FALSE);
}
}
printf("Do you want to play again?");
if (!ja()) break;
}
skip(1);
prout("May the Great Bird of the Galaxy roost upon your home planet.");
return 0;
}
Yes.
This is extensively covered in Using Swift with Cocoa and Objective-C. Objective-C is a superset of C, so all the instructions for Objective-C work equally well for C.
The short version is that you just add the C code to your project, import its header in your Objective-C Bridging Header, and then the C functions will be available in Swift (using various automatic translations).
That said, if you really want to read the output (i.e. the results of these printf) calls, that's a bit different problem. I'd avoid it if you can. Otherwise you'd need to do something like build the C program as its own executable and use NSTask within Swift to call it and capture the output, or you'd have to hijack stdout with something like fdopen. It's a pain to do that completely correctly.
I will focus on the second part of your question, how to interact with C code that uses the standard IO facilities:
The obvious choice as Rob Napier pointed out is just compiling the C code into an executable and using something akin to popen(3) to read and write to its standard IO facilities, the same way you would read/write any other FILE*.
Another way would be to seek out places where stdio is used and change these functions. For example you could use
#ifdef STANDALONE
#define print printf
#else
#define print passToSwift
#endif
Then you can change all the printfs to prints and just #define which mode you want your C code to operate in. In case STANDALONE is left undefined, you will have to provide a passToSwift function that will connect your C and Swift functionality.
One more way without having to change all printfs is using funopen(3) or friends, particularly fwopen(3). With fwopen(3) (man fwopen) you can provide a passToSwift function to be called whenever something is written to stdout.
#include <stdio.h>
int passToSwift(void * cookie, const char * buffer, int len)
{
(void)cookie;
// do stuff with the buffer you recieved
return len;
}
int main(void)
{
fflush(stdout);
stdout = fwopen(NULL, passToSwift);
printf("Hey\n");
}
The assignment to stdout is not portable, but works for me on OS X. I am not aware of any other way to achieve it. (dup2 gives EBADF for funopend streams, freopen expects an entry in the filesystem).
I am adressing a quite similar problem.
I have a solution open to discussion on codereview: C hack: replace printf to collect output and return complete string by using a line buffer
Maybe you could use that (or a part of it) for your text game as well ...
The improved version of C hack: replace printf to collect output and return complete string by using a line buffer is now availabe on github as Xcode 7 project swift-C-string-passing (and standalone gcc version).
Especially look at the #define preprocessor statements to make use of the bridge to swift (similar to a3f's answer).
My solution is able to pass strings in and out to the C code. But how are the answers retrieved from the user? I.e. what does the ja() function do?
I'm writing a function which searches a text file formatted like this:
#User1\pass\
#User2\pass\
#User3\pass\
I have written the function Check_User:
int Check_User(char input[20], FILE *userlist)
{
int c, i;
fseek(userlist, 0, SEEK_SET);
while(1)
{
while((c = fgetc(userlist)) != '#')
{
if(c == EOF)
return 1;
}
while(input[i] == (c = fgetc(userlist)))
{
i++;
}
i = 0;
if(c == '\\')
return 0;
}
}
Which is called from here:
while(Check_User(username, userlist) == 0)
{
printf("Username already in use. Please select another:");
Get_Input(username);
}
Check user checks the file pointed to by *userlist to see if the username[20] contains a username which is already in use. If it is already in use it calls Get_Input for a new username.
The program makes it all the way to the while loop and then gives me a segmentation fault: 11. I have read that this often stems from trying to write beyond the end of an array, or generally doing things to memory you don't have access to. Userlist.txt has been opened in r+ mode.
Thanks for the help.
You did not initialize your variable i before its first use. In C, declared variables are not initialized to numerical 0 (as they would be in C# or Java), but simply use the value that was present at their memory location before. Thus, the value of i may be far bigger that the length of the string input, and input[i] may access an invalid memory location.
As a side note: to quickly debug this yourself under Linux, compile the program with debug symbols (gcc -g) and then use valgrind --tool=memcheck <your program> to let valgrind find the source of error for you.
I am writing some code for a C wordsearch program and, while compiling one of the files, i get segmentation fault on fscanf function but i don't know where the error is.
I already searched for the answer and i understood that on integer variables I must initialize the value of them (and I already done it) and that i must refer the types inside fscanf() with '&' (done it too).
Here is the code( in the main() function):
int i;
int nl = 0;
int nc = 0;
int a, b, d;
char mat[1000][1000];//character matrix for wordsearch letters
int x[1000], y[1000];
int l, c, n;
printf("Chose the wordsearch you want to use.\n For example: t01.in, t02.in, t03.in, t04.in, (...),t30.in\n");
char wordsearch_file[8];
fgets(wordsearch_file,8,stdin);//user enters f.e. 't01.in'
FILE *stream;
char buffer[1024];
sprintf(buffer, "home/adminuser/Desktop/LA/ETAPA2/sopas/%s", wordsearch_file);
stream = fopen(buffer,"r");
if((fscanf (stream,"%d%d", &nl, &nc)) > 0){ // SEG. FAULT happens here
for(l = 0; l < nl; l++) {
for(c = 0; c < nc; c++)
mat[l][c] = fgetc(stream) != EOF;
fgetc(stream);
}
}
I wanted 'nl' (number of lines) to read 3 and 'nc' (number os columns) to read the other 3.
The 't01.in' file:
3 3
SIA
ORR
EDI
Anytime you open an external resource (file, database, socket), or make any system call whatsoever, you always check for a valid stream or return code.
The first thing you should do is add a check for stream instead of blindly calling fscanf(stream,...) without knowing if the fopen() call succeeded.
Then decide why fopen() failed. I suggest printing out the filenamne, or checking that it exists, and/or using perror() to print the system error. perror() will tell you exactly what is wrong, and if I had to guess, it would be as #BLUEPIXY mentioned, a newline in the filename.
stream = fopen(buffer,"r");
if(!stream) {
perror("what the problem: ");
}
Lastly, learn how to use the debugger to analyze the core file. If you aren't getting a core dump, set your ulimit correctly. From memory, you want "ulimit -c unlimited". Find out your current ulimits by typing simply "ulimit" at the shell prompt. Then re-run your crashing program. Once you get a core file, run GNU debugger on it.
gdb program.exe core
If I wanted to run a shell command in linux with a c program, I would use
system("ls");
Is there a way I can accomplish this in Wind River vxworks?
I found the below example but I'm wondering do I need to include vxworks header files for this to work? I assume I do, but how do I figure out which one?
Example:
// This function runs a shell command and captures the output to the
// specified file
//
extern int consoleFd;
typedef unsigned int (*UINTFUNCPTR) ();
extern "C" int shellToFile(char * shellCmd, char * outputFile)
{
int rtn;
int STDFd;
int outFileFd;
outFileFd = creat( outputFile, O_RDWR);
printf("creat returned %x as a file desc\n",outFileFd);
if (outFileFd != -1)
{
STDFd=ioGlobalStdGet(STD_OUT);
ioGlobalStdSet(STD_OUT,outFileFd);
rtn=execute(shellCmd);
if (rtn !=0)
printf("execute returned %d \n",outFileFd);
ioGlobalStdSet(STD_OUT,STDFd);
}
close(outFileFd);
return (rtn);
}
I found the code segment below worked for me. For some reason changing the globalStdOut didn't work. Also the execute function did not work for me. But my setting the specific task out to my file, I was able to obtain the data I needed.
/* This function directs the output from the devs command into a new file*/
int devsToFile(const char * outputFile)
{
int stdTaskFd;
int outputFileFd;
outputFileFd = creat( outputFile, O_RDWR);
if (outputFileFd != ERROR)
{
stdTaskFd = ioTaskStdGet(0,1);
ioTaskStdSet(0,1,outputFileFd);
devs();
ioTaskStdSet(0,1,stdTaskFd);
close(outputFileFd);
return (OK);
}
else
return (ERROR);
}
If this is a target/kernel shell (i.e. running on the target itself), then remember that all the shell commands are simply translated to function calls.
Thus "ls" really is a call to ls(), which I believe is declared in dirLib.h
I think that the ExecCmd function is what you are looking for.
http://www.dholloway.com/vxworks/6.5/man/cat2/ExecCmd.shtml
As ever, read the documentation. ioLib.h is required for most of the functions used in that example, and stdio.h of course for printf().
As to the general question of whether you need to include any particular headers for any code to compile, you do need to declare all symbols used, and generally that means including appropriate headers. The compiler will soon tell you about any undefined symbols, either by warning or error (in C89/90 undefined functions are not an error, just a bad idea).