Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 2 years ago.
Improve this question
I get a segmentation fault before main() when I try to start with command ./somename.o -s 4
Works well when using ./somename.o without key arguments
main.c
#include <stdio.h>
#include <stdlib.h>
#include "input.h"
#include "output.h"
int main(int argc, char** argv) {
input_handler(argc, argv);
pretty_print();
return 0;
}
input.h
#include "data.h"
#include"func.h"
#include <getopt.h>
#include <stdlib.h>
#include <stdio.h>
#include <time.h>
void input_handler(int argc, char** argv);
data.h
#pragma once
void(*func) (void);
void(*input) (void);
static struct Matrix {
int size;
int** A;
}matrix;
GitHub:
https://github.com/sandderson/lab2
EDIT:
added include guards
Also some usefull info:
I use windows subsystem for linux
I compile with makefile and following sequence:
gcc -c func.c
gcc -c input.c
gcc -c main.c
gcc -c output.c
gcc main.o func.o input.o output.o -o Lab2.o
Your call to getopt_long uses "sdi" as the options string, which means that -s, -d and -i are possible options, and that none of them take an argument (since none are followed by a colon). See man getopt for details.
But when you are handling the -s option, you do:
matrix.size = atoi(optarg);
which assumes optarg will be set up to point to an argument. It isn't, because as far as getopt_long is concerned, -s doesn't take an argument. Thus, it has its initial value (NULL) and atoi attempts to use that as a string. Unsurprisingly, a segmentation fault results.
Moreover, your attempt to bracket the error by inserting printf calls fails because you have failed to ensure that the printf is flushed to the actual output device. Stdio buffering makes printf a notoriously inaccurate tool for demonstrating the sequence of actions inside a program; you really cannot assume that an error preceded a call to printf just because the output from the printf was not visible.
Ideally, you should do both of the following (although either one would be sufficient in most cases):
Send debugging output to stderr using fprintf
Terminate debugging lines with a newline character
Eg: fprintf(stderr, "%s\n", "dlfkg");, although you could use a better message.
(Even if you do that, it is possible that the line output to the terminal is overwritten or otherwise fails to be presented as a result of a segfault which occurs soon afterwards. But your odds of seeing the message are a lot better.)
But if you neither of those things, then the most likely outcome is that the characters printed will only be placed in the stdio buffer, where they will stay until the buffer becomes full or a newline is printed (if the device is line-buffered, for which there is no guarantee). When the program blows up as a result of the segfault, the stdio buffers vanish into thin air, so nothing ever gets printed. Thus the non-appearance of the line tells you precisely nothing about the sequence of events.
The small amount of extra typing would have been a lot less than asking this question here and responding to the resulting comments. Just sayin'
Related
I have a C program which waits for user's input
#include <stdio.h>
int main()
{
getchar();
return 0;
}
Now I run it and input some Chinese characters like 测试测试. Then now I click backspace, I found I cannot erase these characters completely(some blank remained)
I found termios has a flag setting IUTF8, but why it doesn't work?
UPDATE ON 2022/12/31:
I am trying to describe my question more detailed, I have a program like this
Now I run it and enter some Chinese characters(without Enter key)
Then I keep clicking Backspace key(until nothing can be erased any more), but half of the content still display on my screen. It's so abnormal, how can I make the erase perform well?
I know it is a stupid question for you. I just want to make it more comfortable when typing some UTF8 characters(like Chinese characters).
I found the shell can handle this well, how can I do to make my program perform the same?
By the way, this is my locale output
LANG=en_US.UTF-8
LC_CTYPE="en_US.UTF-8"
LC_NUMERIC=zh_CN.UTF-8
LC_TIME=zh_CN.UTF-8
LC_COLLATE="en_US.UTF-8"
LC_MONETARY=zh_CN.UTF-8
LC_MESSAGES="en_US.UTF-8"
LC_PAPER=zh_CN.UTF-8
LC_NAME=zh_CN.UTF-8
LC_ADDRESS=zh_CN.UTF-8
LC_TELEPHONE=zh_CN.UTF-8
LC_MEASUREMENT=zh_CN.UTF-8
LC_IDENTIFICATION=zh_CN.UTF-8
LC_ALL=
Use GNU readline to provide a shell-like interface, with Tab autocompletion, correct input handling, et cetera.
To compile the following example program, make sure you have the libreadline-dev package installed. The readline library needed to run the program will already be installed, because so many applications that are installed by default require it already.
// SPDX-License-Identifier: CC0-1.0
// Compile using
// gcc -Wall -O2 $(pkg-config --cflags readline) example.c $(pkg-config --libs readline) -o example
#define _GNU_SOURCE
#include <stdlib.h>
#include <locale.h>
#include <readline/readline.h>
#include <readline/history.h>
#include <stdio.h>
int main(void)
{
char *line;
setlocale(LC_ALL, "");
while (1) {
line = readline(NULL); // No prompt
// Input line is in 'line'; exit if end of input or empty line.
if (!line || *line == '\0')
break;
// Do something with 'line'
// Discard the dynamically allocated line
free(line);
}
return 0;
}
When using the GNU readline library, the library takes over the standard input, and handles character deletion (and many other things) at the terminal (termios) level. It works absolutely fine with file and pipe inputs as well, and is what e.g. bash shell uses for interactive input.
This is my program code:
#include <unistd.h>
#include <stdio.h>
#include <time.h>
#include <stdlib.h>
#include <sys/types.h>
void function() {
srand(time(NULL));
while(1) {
int n = rand();
printf("%d ", n);
//sleep(1);
}
}
int main() {
pid_t pid;
pid = fork();
if (pid == 0) {
function();
}
}
With the sleep line commented out (as in the code above) the program works fine (i.e. it prints a bunch of random numbers too fast to even see if they are actually random), but if I remove the comment the program doesn't print anything and exits (not even the first time, before it gets to the sleep), even though it compiles without warnings or errors with or without the comment.
but if I remove the comment the program doesn't print anything and exits
It does not print, but it does not really exit either. It will still be running a process in the background. And that process runs your infinite while loop.
Using your code in p.c:
$ gcc p.c
$ ./a.out
$ ps -A | grep a.out
267282 pts/0 00:00:00 a.out
$ killall a.out
$ killall a.out
a.out: no process found
The problem is that printf does not really print. It only sends data to the output buffer. In order to force the output buffer to be printed, invoke fflush(stdout)
If you're not flushing, then you just rely on the behavior of the terminal you're using. It's very common for terminals to flush when you write a newline character to the output stream. That's one reason why it's preferable to use printf("data\n") instead of printf("\ndata"). See this question for more info: https://softwareengineering.stackexchange.com/q/381711/283695
I'd suspect that if you just leave your program running, it will eventually print. It makes sense that it has a finite buffer and that it flushes when it gets full. But that's just an (educated) guess, and it depends on your terminal.
it prints a bunch of random numbers too fast to even see if they are actually random
How do you see if a sequence of numbers is random? (Playing the devils advocate)
I believe you need to call fflush(3) from time to time. See also setvbuf(3) and stdio(3) and sysconf(3).
I guess that if you coded:
while(1) {
int n = rand();
printf("%d ", n);
if (n % 4 == 0)
fflush(NULL);
sleep(1);
}
The behavior of your program might be more user friendly. The buffer of stdout might have several dozens of kilobytes at least.
BTW, I could be wrong. Check by reading a recent C draft standard (perhaps n2176).
At the very least, see this C reference website then syscalls(2), fork(2) and sleep(3).
You need to call waitpid(2) or a similar function for every successful fork(2).
If on Linux, read also Advanced Linux Programming and use both strace(1) and gdb(1) to understand the behavior of your program. With GCC don't forget to compile it as gcc -Wall -Wextra -g to get all warnings and debug info.
Consider also using the Clang static analyzer.
For an assignment I have we are to find vulnerabilities in a certain C program and exploit them using various buffer overflow attacks. However when I run the .out file in the terminal with it's input argument it just stalls and doesn't do anything.
Even when I run GDB, that just lags too. I'm not looking for a solution to the assignment, I'm just looking for reasons why it's not running?
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>
void partialwin()
{
printf("Achieved 1/2!\n");
}
void fullwin(){
printf("Achieved 2/2\n");
}
void vuln(){
char buffer[36];
gets(buffer);
printf("Buffer contents are %s\n",buffer);
}
int main(int argc,char**argv){
vuln();
}
Providing your sourc file is called assignment1.c and you're using gcc this should work, $ being your command prompt (which could be different on your platform)
$ gcc assignment1.c
$ a.out
Hello
Buffer contents are Hello
$
It seems that I'm completely misusing mkstemp. However I use it, I always get a segfault. I compiled the most basic program below with gcc -ggdb -Wall -Werror main.c and ran it with ./a.out
#include <stdlib.h>
int main(int argc, char **argv) {
mkstemp("XXXXXX");
return 0;
}
This always returns the returncode 139 and it prints [1] 23532 segmentation fault ./a.out on the terminal. (23532 always changes because it's the pid).
I tried:
switching the flags of gcc (none at all, a lot of combinations of the previous flags, -Wextra and -O0)
Changing the code by saving the resulting filedescriptor in a int, sleeping 5 seconds and closing the filedescriptor again. But I don't even reach the start of the sleep...
And now I'm out of ideas...
From the man page:
The last six characters of template must be "XXXXXX" and these are
replaced with a string that makes the filename unique. Since it will
be modified, template must not be a string constant, but should be
declared as a character array.
So you need to declare a character array:
char filename[] = "fileXXXXXX";
mkstemp(filename);
I have seen a strange behavior with "strndup" call on AIX 5.3 and 6.1.
If I call strndup with size more than the size of actual source string length, then there is a stack corruption after that call.
Following is the sample code where this issue can come:
int main ()
{
char *dst_str = NULL;
char src_str[1023] = "sample string";
dst_str = strndup(src_str, sizeof(src_str));
free(dst_str);
return 0;
}
Does anybody have experienced this behavior?
If yes please let me know.
As per my observation, there must be a patch from OS where this issue got fixed. but i could not get that patch if at all there is any. Please throw some light.
Thanks & Regards,
Thumbeti
You are missing a #include <string.h> in your code. Please try that—I am fairly sure it will work. The reason is that without the #include <string.h>, there is no prototype for strndup() in scope, so the compiler assumes that strndup() returns an int, and takes an unspecified number of parameters. That is obviously wrong. (I am assuming you're compiling in POSIX compliant mode, so strndup() is available to you.)
For this reason, it is always useful to compile code with warnings enabled.
If your problem persists even after the change, there might be a bug.
Edit: Looks like there might be a problem with strndup() on AIX: the problem seems to be in a broken strnlen() function on AIX. If, even after #include <string.h> you see the problem, it is likely you're seeing the bug. A google search shows a long list of results about it.
Edit 2:
Can you please try the following program and post the results?
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
int main(void)
{
char *test1 = "abcdefghijabcdefghijabcdefghijk";
char *test2 = "012345678901234567890123456789";
char *control = "01234567890123456789012345678";
char *verify;
free(strndup(test1, 30));
verify = strndup(test2, 29); /* shorter then first strndup !!! */
fprintf(stderr,">%s<\n",verify);
if (strcmp(control, verify))
printf("strndup is broken\n");
}
(Taken from https://bugzilla.samba.org/show_bug.cgi?id=1097#c10.)
Edit 3: After seeing your output, which is >01234567890123456789012345678<, and with no strndup is broken, I don't think your version of AIX has the strndup bug.
Most likely you are corrupting memory somewhere (given the fact that the problem only appears in a large program, under certain conditions). Can you make a small, complete, compilable example that exhibits the stack corruption problem? Otherwise, you will have to debug your memory allocation/deallocation in your program. There are many programs to help you do that, such as valgrind, glibc mcheck, dmalloc, electricfence, etc.
Old topic, but I have experienced this issue as well. A simple test program on AIX 6.1, in conjunction with AIX's MALLOCDEBUG confirms the issue.
#include <string.h>
int main(void)
{
char test[32] = "1234";
char *newbuf = NULL;
newbuf = strndup(test, sizeof(test)-1);
}
Compile and run the program with buffer overflow detection:
~$ gcc -g test_strndup2.c
~$ MALLOCDEBUG=catch_overflow ./a.out
Segmentation fault (core dumped)
Now run dbx to analyze the core:
~$ dbx ./a.out /var/Corefiles/core.6225952.22190412
Type 'help' for help.
[using memory image in /var/Corefiles/core.6225952.22190412]
reading symbolic information ...
Segmentation fault in strncpy at 0xd0139efc
0xd0139efc (strncpy+0xdc) 9cc50001 stbu r6,0x1(r5)
(dbx) where
strncpy() at 0xd0139efc
strndup#AF5_3(??, ??) at 0xd03f3f34
main(), line 8 in "test_strndup2.c"
Tracing through the instructions in strndup, it appears that it mallocs a buffer that is just large enough to handle the string in s plus a NULL terminator. However, it will always copy n characters to the new buffer, padding with zeros if necessary, causing a buffer overflow if strlen(s) < n.
char* strndup(const char*s, size_t n)
{
char* newbuf = (char*)malloc(strnlen(s, n) + 1);
strncpy(newbuf, s, n-1);
return newbuf;
}
Alok is right. and with the gcc toolchain under glibc, you would need to define _GNU_SOURCE to get the decl of strndup, otherwise it's not decl'd, e.g.:
#include <string.h>
...
compilo:
gcc -D_GNU_SOURCE a.c
Thanks a lot for your prompt responses.
I have tried the given program.
following is the result:
bash-2.05b# ./mystrndup3
>01234567890123456789012345678<
In my program I have included , still problem is persistent.
Following is the strndup declaration in prepossessed code.
extern char * strndup(const char *, size_t);
I would like to clarify one thing, with small program I don't get effect of stack corruption. It is consistently appearing in my product which has huge amount of function calls.
Using strndup in the following way solved the problem:
dst_str = strndup(src_str, srtlen(src_str));
Please note: used strlen instead of sizeof as i need only the valid string.
I am trying to understand why it is happening.
Behavior i am seeing with my product when i use strndup with large size:
At the "exit" of main, execution is coring with "illegal instruction"
intermittently "Illegal Instruction" in the middle of execution (after strndup call).
Corrupt of some allocated memory, which is no where related to strndup.
All these issues are resolved by just modifying the usage of strndup with actual size of source string.
Thanks & Regards,
Thumbeti