Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 6 years ago.
Improve this question
Is there a preferable way to report errors in C? For example if a file that is supposed to be opened does not exist, should I use
if( fp == NULL )
{
perror("Error: ");
return(-1);
}
(copied from http://www.tutorialspoint.com/c_standard_library/c_function_perror.htm )
or
if( fp == NULL )
{
fprintf(stderr, "Unable to open file for reading.\n");
return(-1);
}
You can use perror() or strerror to get the error message. If you want to postpone the display of error message or if you want to log the message to a file, then save the errno and use strerror() because perror only writes to the standard error stream and it uses the global errno set and the errno might change any time if any library function is called before printing the error message.
Example using saved errno:
int savederrno;
....
if( fp == NULL )
{
savederrno = errno; /* Save the errno immediately after an api/lib function or a system call */
/*If you want to write to a log file now, write here using strerror and other library calls */
}
....
/* use strerror function to get the error message and write to log
or write to std error etc*/
The following man pages explain the error reporting in detail.
http://www.gnu.org/software/libc/manual/html_node/Error-Messages.html
http://man7.org/linux/man-pages/man3/errno.3.html
tutorialspoint.com is extremely terrible (at least when it comes to C) and as such must not be used. The standard resource to learn from is "The C Programming Language, 2nd edition" by Kernighan and Ritchie.
The preferred way to report stuff is to include the failing function in the message and use perror, e.g. perror("open")
EDIT: originally this did not include any justification for the claim about the site. I did not feel like it is necessary nor sensible. There is no write up I could link to either. They key was to avoid the site and everyone interested can easily conclude material in there is questionable at best and straight up wrong at worst.
However, since I got a weird backlash here are some excerpts:
http://www.tutorialspoint.com/c_standard_library/c_function_malloc.htm
#include <stdio.h>
#include <stdlib.h>
Missing include for strcpy and strcat.
int main()
{
char *str;
/* Initial memory allocation */
str = (char *) malloc(15);
No need to cast malloc. Missing null-check. Why the 15?
strcpy(str, "tutorialspoint");
Bad error-inducing style. What if the length was to change? If an explicit allocation really needs to happen, strlen() + 1 can be used to get the needed size.
printf("String = %s, Address = %u\n", str, str);
'u' is an incorrect specifier for pointer type.
/* Reallocating memory */
str = (char *) realloc(str, 25);
Standard bad idiom. The code should use a temporary pointer to recover from error, or if recovery is not an option, exit.
strcat(str, ".com");
What's up with realloc from 15 to 25 just to add ".com"?
printf("String = %s, Address = %u\n", str, str);
free(str);
return(0);
}
Does this justify my claim about the site?
Related
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 2 years ago.
Improve this question
I would like to merge two files using open and file descriptor. Moreover I would like to separate the content of the first file with - before writing the the content of the second file.
I did the following :
void merge (char* fileName, char *fileName1) {
int fd = open(fileName, O_RDWR);
char c;
while (read(fd, c, 1) > 0) {//going at the end of the first file
}
char next[] = "\n";
char charc[] = "-";
write (fd, next, strlen(next));
for (int i = 0; i < 80; i++) {
if (write (fd, charc, strlen(charc)) == -1) {
perror("error : ");
}
}
write (fd, next, strlen(next));
int fd1 = open(fileName1, O_RDWR);
while(read(fd1, &c, 1) > 0) {
write(fd, &c, sizeof(c));
}
close(fd1);
close(fd);
}
Is there a better way to write this code ? Moreover I have a little problem even if it works it seems like I don't have the right to read the new file. For example if I do cat newFile I have a permission denied.
Is there a better way to write this code ?
You are not handling errors of all calls. All of syscalls open, write, read and close return -1 on error and set errno and may do that at any time. EINTR could be handled.
going at the end of the first file open has O_APPEND flag mode that is used for appending data.
Copying one character at a time is very not optimal. With glibc standard library you could use BUFSIZ bytes at a time that is chosen for fast I/O output. You could make a copy of a big chunk size at a time that is a power of 2, like 2048 or 4096.
There is little reason to use file descriptors here - prefer to use standard FILE * handling, which would make your code portable and also buffer the data for faster I/O.
If you wish to create the file use O_CREAT and add the third argument to open that is the mask of permissions of new file.
On linux there is splice(2) system call that can be used to append data on kernel side for maximum efficiency.
Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 6 years ago.
Improve this question
I'm putting some very temporary debug prints into various userspace programs to figure out what code runs on an embedded Linux device, and I want these prints to write to a file without leaving it open. To make the debug more portable between the various programs, it would be nice to have a one-liner that can open a file, write to it, and close it without having to define a function/macro elsewhere. I could do something like:
{ FILE *f = fopen("filename", "a"); if (f) { fprintf(f, "DEBUG MSG\n"); fclose(f); } else printf("File open error!\n"); }
which is just removing the whitespace from:
{
FILE *f = fopen("filename", "a");
if (f) {
fprintf(f, "DEBUG MSG\n");
fclose(f);
}
else
printf("File open error!\n");
}
But this feels needlessly complex. Is there some more simplified way of doing this? Again, I'm not talking about making it a function, as I'd like it to be copy/pasted between separate programs without defining a function every time. It's just basically a temporary printk equivalent for userspace.
Functions.
Extra chars for my shortest answer.
Potential problem with fprintf(f, "DEBUG MSG\n");
I assume "DEBUG MSG\n" is some placeholder for the true message. Should the true message contain a '%', then the function will look for missing arguments. Use fputs() - its can be lighter on the CPU too than fprintf().
fputs(debug_message, f);
The true message may lack a '\n' and then get stuck in buffering just prior to a program crash. Best to flush when you are done.
fputs(debug_message, f);
fflush(f);
Pedantic: Debugging is for problem solving. Too often the message itself is questionable/corrupt. Consider using protection. (I do not trust excessive long debug messages). Of course the more junk in the fprintf(), the greater the performance impact of debug logging.
if (f) {
if (debug_message) {
fprintf(f, "%.99s", debug_message);
fflush(f);
fclose(f);
}
}
As mentioned by #Tom Karzes, send diagnostic message to stderr, rather than stdout.
Overall, I would use a function call wrapped in a conditional macro rather than embedded code. YMMV.
#ifdef NDEBUG
#define DEBUG_PUTS(level, s)
#else
#define DEBUG_PUTS(level, s) debug_puts((level), __FILE__, __LINE__, (s))
#endif
As mentioned by Mark Plotnick, a workaround for Linux systems is:
system("echo DEBUG MSG >> filename");
It's not pretty but it's quick, copy/pasteable, and easy to use for this situation because it can also write to /dev/kmsg:
system("echo DEBUG MSG >> /dev/kmsg");
which allows it to behave like a printk. Of course, it's not a safe solution and can't be used with any chars that interfere with a bash echo, but for a temporary static debug message it works fine.
Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 7 years ago.
Improve this question
I am trying to create a call to system using custom parameters. However I think that I am incorrectly malloc-ing the size of the final char*.
So I instead get a Failed to Open source file error during the system call. Am I doing something wrong in terms of syntax?
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(void)
{
char program_name[] = "/usr/local/bin/some_program";
char argument_1[] = "foo";
char argument_2[] = "foo2";
char space[] = " ";
char *runProgram = malloc( strlen(program_name) + strlen(argument_1)+
strlen(argument_2) + 2*strlen(space) + 1);
strcpy(runProgram, program_name);
strcat(runProgram, space);
strcat(runProgram, argument_1);
strcat(runProgram, space);
strcat(runProgram, argument_2);
system(runProgram);
free(runProgram);
exit(0);
}
When I run your code, your string appears to contain exactly what it needs to to be called. I do have a suggestion to simplify building it though:
...
int ret=0;
int len = strlen(program_name) + strlen(argument_1)+ strlen(argument_2) + 2*strlen(space) + 1;
char *runProgram = malloc( len);
ret = snprintf(runProgram, len, "%s %s %s", program_name, argument_1, argument_2);
if(ret < 0)
{
//handle if truncation occurred (returns -1 for truncation)
}
if(ret >= len)
{
//use runProgram buffer
}
system(runProgram);
free(runProgram);
//exit(0);
return 0;
...
Have you verified the chmod settings on the file to be executed are correct?
chmod +x /usr/local/bin/some_program
EDIT:
To address concern in comments regarding variations in implementation/documentation for snprintf(). When discussing standard C functions, the hope would be that implementations of the same function would be equal across platforms, but for snprintf(), it appears that some implementations are more equal than others...
1) snprintf some have referred to this as Microsoft's broken implementation.
2) snprintf from skrenta.com
3) snprintf from opengroup.org.
4) snprintf from linux.die.net, (includes glibc references, macros and other comments)
Your code should work fine, printf("cmd is '%s'\n", runProgram); to check if generated command can be run in shell and produces expected results:
command string is correct
/usr/local/bin/some_program exists and has correct permissions
some_program does not fail
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 8 years ago.
Improve this question
I have a HTML file that I've retrieved through curl and I wanted to find certain strings in the file so that I could analyse whether I have received the response I expected.
Here's the function I'm using to search for my string:
int find_str(FILE *infile, char *str)
{
char tmp[512];
while(fgets(tmp, sizeof(tmp), infile) != NULL)
{
if (strstr(tmp, str) != NULL)
{
printf("found %s in file\n", str);
return 1;
}
}
fprintf(stderr, "Couldn't Find %s in file!\n", str);
return 0;
}
and it's called as follows:
if(find_str(html_file, "<h1>Hello World</h1>") == 1)
{ ... }
First, the string is never found even when it is present. Second, this function is called in another if statement if the first should fail, but while watching execution in the debugger, it completely skips the while loop. No garbage values are given. If I watch the tmp array, the values seem normal, although they seem to have been encoded.
With that function, if your search string sits around 512 byte boundaries in the file, it won't match because you only check inside 512 byte blocks.
To fix this issue, you can load the whole file into memory instead. This also has an advantage on performance if you decide to search multiple times, as you won't have to do I/O every time.
This should work to read a file into memory:
fseek (infile, 0 , SEEK_END);
int filesize = ftell (infile);
rewind (infile);
char *whole_file = malloc(filesize+1);
if (!(filesize == fread(whole_file, filesize, 1, infile))) {
// ERROR
}
whole_file[filesize] = '\0';
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 9 years ago.
Improve this question
This error occurred in my program:
Debug Assertion Failed!
Program:C:\JM\.\bin\ldecod.exe
File: f:\ff\vctools\crt_bld\self_x86\crt\src\fscanf.c
Line:52
Expression: (stream!=NULL)
For information on how your program can cause an assertion
failure, see the Visual C++ documentation on asserts.
(Press Retry to debug the application.)
What seems to be the problem here?
CODE
This is the portion of my code where I used fscanf. When mi=297 it worked perfectly fine.
int myframe[29699];
........
if (CONCEAL==1)
{
FILE*concealfile;
concealfile=fopen("myerrsim%15carphone.txt","r");
for(mi=0; mi<14850; mi++)
{
fscanf(concealfile,"%d\n", &myframe[mi]);
}
if (myctr==currMB->mbAddrX+(((currMB)->p_Slice)->p_Img)->number*99 && currMB->mbAddrX+(((currMB)->p_Slice)->p_Img)->number>0)
{
if (myframe[myctr]==1)
{
mbmode=0;
}
myctr++;
}
}
Additional questions! I am encountering several similar errors. The
programs breaks at different portions of source codes and some of
which are built in functions like "fscanf". I do not know the reason.
And sometimes a program on my computer, like "Flash Player" notifies
me of some sort of error. Is this because the pointers used in my
program are trying to access "Flash Player"? Why is this happening and
what is the possible fix?
What are assertion errors simply put?
For #Jonathan Leffler
#ifdef _DEBUG
/*
* Report error.
*
* If _CRT_ERROR has _CRTDBG_REPORT_WNDW on, and user chooses
* "Retry", call the debugger.
*
* Otherwise, continue execution.
*
*/
if (rterrnum != _RT_CRNL && rterrnum != _RT_BANNER && rterrnum != _RT_CRT_NOTINIT)
{
switch (_CrtDbgReportW(_CRT_ERROR, NULL, 0, NULL, L"%s", error_text))
{
-> case 1: _CrtDbgBreak(); msgshown = 1; break;
case 0: msgshown = 1; break;
}
}
where -> is the unexpected breakpoint.
located in C:\Program Files\Microsoft Visual Studio 11.0\VC\crt\src\crt0msg.c
It appears you did something like:
char name[64];
FILE *fp = fopen("c:/non-existent/file", "r");
fscanf(fp, "%s", name);
without checking that fopen() was successful, and fprintf() triggered an assertion failure. When fopen() fails, it returns a NULL pointer, and the assertion says stream != NULL (where 'stream' is a file stream, the first argument to fscanf(), and means aFILE *such asfp`).
There's an outside chance that you use fscanf_s() because you're on Windows — it's the same basic story, but fscanf_s() checks for such problems where fscanf() does not.
Possible fix:
char name[64];
FILE *fp = fopen("c:/non-existent/file", "r");
if (fp == 0)
...report failure to open file (and exit or return)...
if (fscanf(fp, "%s", name) != 1)
...report read failure...