Cannot access memory at address using gdb in CLION IDE. How do I setup gdb? - debugging

I get the error "Cannot access memory at address 0x100403055" when I try and set a memory value to 0x00 when stopped in the debugger.
Is there a special switch I need to set to enable the set operation?
Here is my complete C code file "main.c"
#include <stdio.h>
#include <string.h>
/*
separator - consume all non-token characters until next token. This includes:
comments: '#'
nesting: '{'
unnesting: '}'
whitespace: ' ','\t','\n'
*nest is changed according to nesting/unnesting processed
*/
static void separator(int *nest, char **tokens) {
char c, *s;
s = *tokens;
while ((c = *s)) {
/* #->eol = comment */
if (c == '#') {
s++;
while ((c = *s)) {
s++;
if (c == '\n')
break;
}
continue;
}
if (c == '{') {
(*nest)++;
s++;
continue;
}
if (c == '}') {
(*nest)--;
s++;
continue;
}
if (c == ' ' || c == '\n' || c == '\t') {
s++;
continue;
}
break;
}
*tokens = s;
}
/*
token - capture all characters until next separator, then consume separator,
return captured token, leave **tokens pointing to next token.
*/
static char *token(int *nest, char **tokens) {
char c, *s, *t;
char terminator = '\0';
s = t = *tokens;
while ((c = *s)) {
if (c == '#'
|| c == ' ' || c == '\t' || c == '\n' || c == '{' || c == '}')
break;
s++;
}
*tokens = s;
separator(nest, tokens);
/* Breakpoint here to examine and manipulate memory */
*s = '\0';
return t;
}
struct test_case {
char *input;
int nest;
char *expected_output;
};
int main() {
int nest = 0;
int TESTSEP = 0;
if (TESTSEP>0) {
char *tokens = "# this is a comment\n{nesting {example} unnesting}\n \t end";
separator(&nest, &tokens);
printf("nest: %d\n", nest);
printf("tokens: %s\n", tokens);
return 0;
} else {
struct test_case test_cases[] = {
{"hello world", 0, "hello"},
{"hello#world", 0, "hello"},
{"hello{world}", 0, "hello"},
{"hello world", 0, "hello"},
{"hello\tworld", 0, "hello"},
{"hello\nworld", 0, "hello"},
};
for (int i = 0; i < sizeof(test_cases) / sizeof(test_cases[0]); i++) {
struct test_case test_case = test_cases[i];
char *tokens = test_case.input;
char *output = token(&test_case.nest, &tokens);
if (strcmp(output, test_case.expected_output) != 0) {
printf("Test case %d failed: expected %s, got %s\n", i, test_case.expected_output, output);
}
}
return 0;
}
}
In the token function there is a comment line where I place a breakpoint and drop into the gdb debugger. The code is supposed to write a '\0' at the address of the pointer *s to truncate the string.
When I'm in the debugger and I examine the 's' variable I get the following:
(gdb) x s
0x100403055: 0x726f7720
When I try and set the variable I get:
(gdb) [![set *0x0000000100403055 = 0x726f7700][1]][1]
Cannot access memory at address 0x100403055
I'm using the CLION IDE and am a novice. I'm not sure if its an IDE problem, a user problem or some external memory protection mechanism that is preventing this.
Does anyone know how to make this work?
Here is a screenshot of the IDE:
When I run the code (without the debugger) I get this output:
./explore.exe
Test case 0 failed: expected hello, got hello world
Test case 1 failed: expected hello, got hello#world
Test case 2 failed: expected hello, got hello{world}
Test case 3 failed: expected hello, got hello world
Test case 4 failed: expected hello, got hello world
Test case 5 failed: expected hello, got hello world
Process finished with exit code 0

I this case I believe I was passing in a pointer to memory in the read only space. The struct test_case is built into the code and is read only. So that when I pass that into the token function it was trying to write to read only.
Here is the code that seems to work.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
/*
separator - consume all non-token characters until next token.
This includes:
comments: '#' ... '\n'
nesting: '{'
unnesting: '}'
whitespace: ' ','\t','\n'
*nest is changed according to nesting/unnesting processed
*/
static void separator(int *nest, char **tokens) {
char c, *s;
s = *tokens;
while ((c = *s)) {
/* #->eol = comment */
if (c == '#') {
s++;
while ((c = *s)) {
s++;
if (c == '\n')
break;
}
continue;
}
if (c == '{') {
(*nest)++;
s++;
continue;
}
if (c == '}') {
(*nest)--;
s++;
continue;
}
if (c == ' ' || c == '\n' || c == '\t') {
s++;
continue;
}
break;
}
*tokens = s;
}
/*
token - capture all characters until next separator, then consume
separator,
return captured token, leave **tokens pointing to next token.
*/
static char *token(int *nest, char **tokens) {
char c, *s, *t;
char terminator = '\0';
s = t = *tokens;
while ((c = *s)) {
if (c == '#'
|| c == ' ' || c == '\t' || c == '\n' || c == '{' || c == '}')
break;
s++;
}
*tokens = s;
separator(nest, tokens);
*s = '\0';
return t;
}
struct test_case {
char *input;
int nest;
char *expected_output;
};
int main() {
int nest = 0;
int TESTSEP = 0;
char *temp_malloc_string;
if (TESTSEP>0) {
char *tokens = "# this is a comment\n{nesting {example}
unnesting}\n \t end";
temp_malloc_string = malloc(strlen(tokens)*sizeof(char));
strcpy(temp_malloc_string, tokens);
char * t = token(&nest, &temp_malloc_string);
printf("nest: %d\n", nest);
printf("tokens: %s\n", t);
separator(&nest, &temp_malloc_string);
printf("nest: %d\n", nest);
printf("tokens: %s\n", temp_malloc_string);
return 0;
} else {
struct test_case test_cases[] = {
{"hello world", 0, "hello"},
{"hello#world", 0, "hello"},
{"hello{world}", 0, "hello"},
{"hello world", 0, "hello"},
{"hello\tworld", 0, "hello"},
{"hello\nworld", 0, "hello"},
};
for (int i = 0; i < sizeof(test_cases) / sizeof(test_cases[0]); i++) {
struct test_case test_case = test_cases[i];
char *tokens = test_case.input;
printf("len of string is %d\n", strlen(tokens));
temp_malloc_string = malloc((strlen(tokens)+1)*sizeof(char));
char * tt = temp_malloc_string;
if ( temp_malloc_string==NULL ) {
printf("error!\n");
}
strcpy(temp_malloc_string, tokens);
printf("tm going in: %s\n", temp_malloc_string);
char *output = token(&test_case.nest, &temp_malloc_string);
printf("Test case %d: expected %s, got %s\n\t\ttm is now: %s\n",
i, test_case.expected_output, output, temp_malloc_string);
if (strcmp(output, test_case.expected_output) != 0) {
printf("Test case %d failed: expected %s, got %s\n",
i, test_case.expected_output, output);
}
free(tt);
temp_malloc_string = NULL;
}
return 0;
}
}
Now when I run the code I get:
./explore.exe
len of string is 11
tm going in: hello world
Test case 0: expected hello, got hello
tm is now: world
len of string is 11
tm going in: hello#world
Test case 1: expected hello, got hello
tm is now:
len of string is 12
tm going in: hello{world}
Test case 2: expected hello, got hello
tm is now: world}
len of string is 12
tm going in: hello world
Test case 3: expected hello, got hello
tm is now: world
len of string is 11
tm going in: hello world
Test case 4: expected hello, got hello
tm is now: world
len of string is 11
tm going in: hello
world
Test case 5: expected hello, got hello
tm is now: world
Process finished with exit code 0
And when I stop at the breakpoint I can write to memory.
In this modified code I malloc a char* object and copy the string from the struct into that then pass that into the token function.
I'm guess that gdb is protecting me from writing to the .text block in code.
Like I said: I'm a newbie :(

Related

Any faster way to replace substring in AWK

I have a long string of about 50,000,000 long... , and I am substituting it part by part
cat FILE | tail -n+2 | awk -v k=100 '{
i = 1
while (i<length($0)-k+1) {
x = substr($0, i, k)
if (CONDITION) {
x changed sth
$0 = substr($0,1,i-1) x substr($0,i+k)
}
i += 1
}
gsub(sth,sth,$0)
printf("%s",$0) >> FILE
}'
Are there any ways to replace $0 at position i with x of length k without using this method?
The string is too long and the commands runs extremely slow
sample input:
NNNNNNNNNNggcaaacagaatccagcagcacatcaaaaagcttatccacAGTAATTCATTATATCAAAATGCTCCAggccaggcgtggtggcttatgcc
sample output:
NNNNNNNNNNggcnnncngnnnccngcngcncnncnnnnngcnnnnccncNGNNNNNCNNNNNNNCNNNNNGCNCCNggccnggcgnggnggcnnnngcc
If substring with length k=10 contains >50% of A || a || T || t
(so there are length($0)-k+1 substrings)
substitute A and T with N, a and t with n
The $0 string must maintain it size and sequence (Case sensitive)
EDIT:
I misunderstood the requirement of this problem, and repost the question at here.
Basically:
read a window of characters to two buffers - scratch buffer and output buffer
if in the scratch buffer there are more then some count of characters ATat
then replace all characters ATat in the output buffer buffer to Nn respectively
output one character from the output buffer
flush one character in both buffers
and go to step 1 to repeat reading the characters into buffers
when the end of line is encountered, just flush output buffer and reset it all
A small C program for sure is going to be the fastest:
// The window size
#define N 10
// The percent of the window that has to be equal to one of [AaTt]
#define PERCENT 50
#include <assert.h>
#include <stdio.h>
#include <string.h>
#include <stdbool.h>
// output a string
static void output(char *outme, size_t n) {
fwrite(outme, n, 1, stdout);
}
// is one of [AaTt]
static bool is_one_of_them(char c) {
switch(c) {
case 'A':
case 'a':
case 'T':
case 't':
return true;
}
return false;
}
// Convert one of characters to n/N depending on case
static char convert_them_to_n(char c) {
// switch(c){ case 'T': case 'A': return true; } return false;
// ASCII is assumed
const char m = ~0x1f;
const char w = 'n' & ~m;
return (c & m) | w;
}
static const unsigned threshold = N * PERCENT / 100;
// Store the input in buf
static char buf[N];
// Store the output to-be-outputted in out
static char out[N];
// The current position in buf and out
// The count of readed characters
static size_t pos;
// The count of one of searched characters in buf
static unsigned count_them;
static void buf_reset(void) {
pos = 0;
count_them = 0;
}
static void buf_flush(void) {
output(out, pos);
buf_reset();
}
static void buf_replace_them(void) {
// TODO: this could keep count of characters alrady replaced in out to save CPU
for (size_t i = 0; i < N; ++i) {
if (is_one_of_them(out[i])) {
out[i] = convert_them_to_n(out[i]);
}
}
}
static void buf_flush_one(void) {
assert(pos > 0);
assert(pos == N);
output(out, 1);
count_them -= is_one_of_them(buf[0]);
memmove(buf, buf + 1, pos - 1);
memmove(out, out + 1, pos - 1);
pos--;
}
static void buf_add(char c) {
buf[pos] = out[pos] = c;
pos++;
count_them += is_one_of_them(c);
// if we reached the substring length
if (pos == N) {
// if the count reached the threshold
if (count_them >= threshold) {
// convert the characters to n
buf_replace_them();
}
// flush one character only at a time
buf_flush_one();
}
}
int main() {
int c;
buf_reset();
while ((c = getchar()) != EOF) {
if (c == '\n') {
// If its a newline, just flush what we have buffered
buf_flush();
output("\n", 1);
continue;
}
buf_add(c);
}
buf_flush();
}
Such a C program is easily transferable to for example an awk script, just one need to read one character at a time. Below I split the characters with split, like:
awk -v N=10 -v percent=50 '
BEGIN{ threshold = N * percent / 100; pos=0 }
function is_one_of_them(c) {
return c ~ /^[aAtT]$/;
}
function buf_flush(i) {
for (i = 0; i < pos; ++i) {
printf "%s", out[i]
}
pos = 0
count_them = 0
}
function buf_replace_them(i) {
for (i = 0; i < pos; ++i) {
if (is_one_of_them(out[i])) {
out[i] = out[i] ~ /[AT]/ ? "N" : "n";
}
}
}
function buf_flush_one(i) {
printf "%s", out[0]
count_them -= is_one_of_them(buf[0])
if(0 && debug) {
printf(" count_them %s ", count_them)
for (i = 0; i < pos-1; ++i) {
printf("%s", buf[i+1])
} printf(" ");
for (i = 0; i < pos-1; ++i) {
printf("%s", out[i+1])
}
printf("\n");
}
for (i = 0; i < pos-1; ++i) {
buf[i] = buf[i+1]
out[i] = out[i+1]
}
pos--
}
function buf_add(c) {
buf[pos]=c; out[pos]=c; pos++
count_them += is_one_of_them(c)
if (pos == N) {
if (count_them >= threshold) {
buf_replace_them()
}
buf_flush_one()
}
}
{
split($0, chars, "")
for (idx = 0; idx <= length($0); idx++) {
buf_add(chars[idx])
}
buf_flush();
printf "\n";
}
'
Both programs when run with the input presented in the first line produce the output presented in the second line (note that lone a near the end is not replaced, because there are no 5 charactets ATat in a window of 10 characters from it):
NNNNNNNNNNggcaaacagaatccagcagcacatcaaaaagcttatccacAGTAATTCATTATATCAAAATGCTCCAggccaggcgtggtggcttatgcc
NNNNNNNNNNggcnnncngnnnccngcngcncnncnnnnngcnnnnccncNGNNNNNCNNNNNNNCNNNNNGCNCCNggccaggcgnggnggcnnnngcc
Both solutions were tested on repl.
You need to be careful with how you address this problem. You cannot work on the substituted string. You need to keep track of the original string. Here is a simple example. Assume we have a string consisting of x and y and we want to replace all y with z if there are 8 y in a substring of 10. Imagine your input looks like:
yyyyyyyyxxy
The first substring of 10 reads yyyyyyyyxx and would be translated into zzzzzzzzxx. If you perform the substitution directly into the original string, you get zzzzzzzzxxy. The second substring now reads zzzzzzzxxy, and does not contain 8 times y, while in the original string it does. So according to the solution of the OP, this would lead into inconsistent results, depending on if you start from the front or the back. So a quick solution would be:
awk -v N=10 -v p=50 '
BEGIN { n = N*p/100 }
{ s = $0 }
{ for(i=1;i<=length-N;++i) {
str=substr($0,i,N)
c=gsub(/[AT]/,"N",str) + gsub(/[at]/,"n",str)
if(c >= n) s = substr(s,1,i-1) str substr(s,i+N)
}
}
{ print s }' file
There is ofcourse quite some work you do double here. Imagine you have a string of the form xxyyyyyyyyxx, you would perform 4 concatinations while you only need to do one. So the best idea is to minimalise the work and only check the substrings which end with the respective character:
awk -v N=10 -v p=50 '
BEGIN { n = N*p/100 }
{ s = $0 }
{ i=N; while (match(substr($0,i),/[ATat]/)) {
str=substr($0,i+RSTART-N,N)
c=gsub(/[AT]/,"N",str) + gsub(/[at]/,"n",str)
if(c >= n) { s = substr(s,1,i+RSTART-N-1) str substr(s,i+RSTART)}
i=i+RSTART
}
}
{ print s }' file
To replace $0 at position i with x do:
awk 'BEGIN{i=12345;x="blubber"}
{
printf("%s",substr($0,1,i));
printf("%s",x);
printf("%s",substr($0,i+length(x)));
}'
I don't think there is any faster method.
To replace AGCT with N and agct with n use tr. To replace them only within a range and using awk you should do:
awk 'BEGIN{i=12345;n=123}
{
printf("%s",substr($0,1,i-1));
printf(gsub(/[atgc]/,"n",gsub(/[ATGC]/,"N",substr($0,i,i+n-1))));
printf("%s",substr($0,i+n));
}'
To do more advanced and faster processing you should consider c/c++.

Spoj question ONP Transform the expression giving signal abort

I am trying to solve ONP - Transform the Expression in spoj. The question is to transform infix expression into postfix expression. I have used std::stack as my data structure and shunting-yard algorithm for solving it. The code runs fine on my computer using g++. But on spoj, it gives SIGABRT error. Even on ideone, it gives run time error free() invalid pointer.
I have tried several test cases. At first, I thought that my program was taking too much memory, but upon testing with time -v (ubuntu), I found that the maximum space taken was in KB.
// ------------------- infix to postfix conversion ---------------
#include <iostream>
#include <string>
#include <stack>
#include <algorithm>
#include <utility>
using std::stack;
using std::pair;
using std::cout;
using std::cin;
using std::endl;
using std::string;
stack< pair<char, short> > op_st; // operator stack
short op_precedence(char op) {
// return operator precedence
// input: operator; output: its precedence value
switch (op) {
case '+': return 0;
case '-': return 1;
case '*': return 2;
case '/': return 3;
case '^': return 4;
case '(': return 6;
}
}
inline bool is_operator(char sym) {
// is sym an operator?
return (sym == '+' || sym == '-' || sym == '*' || sym == '/' || sym == '^' || sym == '(');
}
inline bool is_operand(char sym) {
// is sym an operand?
return (sym >= 'a' && sym <= 'z');
}
void in_to_post(string & expr) {
// infix to postfix converter
// input: infix expression
for (int i = 0; i < expr.length(); ++i) {
if (is_operator(expr[i])) { // operator
// pop op_stack until the
// top of the stack has less precedence
// than curr operator or stack is empty
while(1) {
if (op_st.empty()) { // stack is empty; straight away push
op_st.push(std::make_pair(expr[i], op_precedence(expr[i])));
break;
}
pair <char, short> & top_op = op_st.top();
if (op_precedence(top_op.second) >= op_precedence(expr[i])) {
cout << top_op.first;
op_st.pop();
}
else {
op_st.push(std::make_pair(expr[i], op_precedence(expr[i])));
break;
}
}
}
else if (is_operand(expr[i])) { // operand; push it to output queue immediately
cout << expr[i];
}
else if (expr[i] == ')') { // right paranthesis
while (1) {
if (op_st.empty()) { // invalid expression; ')' reached before matching '('
//cout << "No matching '(' found\n";
abort();
}
pair <char, short> & top_op = op_st.top();
if (top_op.first == '(') { // matching '(' found; stop
op_st.pop();
break;
}
else {
cout << top_op.first;
op_st.pop();
}
}
}
}
// pop out the whole op_st (if any)
while (!(op_st.empty())) {
pair <char, short> & top_op = op_st.top();
cout << top_op.first;
op_st.pop();
}
}
int main() {
int t;
cin >> t;
for (int i = 0; i < t; ++i) {
string expr;
cin >> expr;
//cout << expr.length() << endl;
in_to_post(expr);
cout << "\n";
}
return 0;
}
Input to program given on my system:
((a+b)-c*(d+e))^((a+b)-c*(d+e))+((a+b)-c*(d+e))-((a+b)-c*(d+e))+((a+b)-c*(d+e))^((a+b)-c*(d+e))+((a+b)-c*(d+e))-((a+b)-c*(d+e))-((a+b)-c*(d+e))^((a+b)-c*(d+e))+((a+b)-c*(d+e))-((a+b)-c*(d+e))*((a+b)-c*(d+e))^((a+b)-c*(d+e))+((a+b)-c*(d+e))-((a+b)-c*(d+e))^((a+b)-c*(d+e))^((a+b)-c*(d+e))+((a+b)-c*(d+e))-((a+b)-c*(d+e))+((a+b)-c*(d+e))^((a+b)-c*(d+e))+((a+b)-c*(d+e))-((a+b)-c*(d+e))^((a+b)-c*(d+e))^((a+b)-c*(d+e))+((a+b)-c*(d+e))-((a+b)-c*(d+e))
Successfully gives the output:
ab+cde+*-ab+cde+*-ab+cde+*-ab+cde+*-ab+cde+*-ab+cde+*-ab+cde+*-ab+cde+*-ab+cde+*-ab+cde+*-ab+cde+*-ab+cde+*-ab+cde+*-ab+cde+*-ab+cde+*-ab+cde+*-ab+cde+*-ab+cde+*-ab+cde+*-ab+cde+*-ab+cde+*-ab+cde+*-ab+cde+*-ab+cde+*-ab+cde+*-ab+cde+*-ab+cde+*-ab+cde+*--+^^-+^+-+^^-+^*-+^--+^+-+^.
But, the same code gives free() invalid pointer error in ideone. Why is that?
op_precedence(top_op.second) calls op_precedence with the number returned by earlier op_precedence call - not with the operator character.
When op_precedence is passed an argument that doesn't match one of the recognized operators, the program exhibits undefined behavior, by way of reaching the end of a non-void function without encountering a return statement.
So, after Igor Tandetnik kindly pointed the mistake to me, in line 58, I changed op_precedence(top_op.second) to top_op.second. I also added default case to op_precedence function to correct the warning. After compiling and running, this code did actually abort() on line 75 for simple input ((a+b)). It turns out, that my implementation of the algorithm was wrong. My code didn't take into consideration associativity of operator '('. According to the question, we don't need to take into consideration associativity for other operators but for '(' we need its precedence to be higher than all other operators when outside of the stack, and lower than all other operators when inside of the stack. This is to ensure that when any operator other than '(' is the input and the top of the stack is '(', we could push the input operator into the stack. The corrected code is below:
// ------------------- infix to postfix conversion ---------------
#include <iostream>
#include <string>
#include <stack>
#include <algorithm>
#include <utility>
using std::stack;
using std::pair;
using std::cout;
using std::cin;
using std::endl;
using std::string;
short op_out_precedence(char op) {
// return operator precedence (when outside of stack)
// in and out precedence is to take care of associativity
// Here we don't require the associativity of any other operator except '('
// input: operator; output: its precedence value
switch (op) {
case '+': return 1;
case '-': return 2;
case '*': return 3;
case '/': return 4;
case '^': return 5;
case '(': return 6;
default : abort(); // not supposed to happen
// operator can't be other than the mentioned cases
}
}
short op_in_precedence(char op) {
// return operator precedence (when inside of stack)
// in and out precedence is to take care of associativity
// Here we don't require the associativity of any other operator except '('
// input: operator; output: its precedence value
switch (op) {
case '+': return 1;
case '-': return 2;
case '*': return 3;
case '/': return 4;
case '^': return 5;
case '(': return 0;
default : abort(); // not supposed to happen
// operator can't be other than the mentioned cases
}
}
inline bool is_operator(char sym) {
// is sym an operator?
return (sym == '+' || sym == '-' || sym == '*' || sym == '/' || sym == '^' || sym == '(');
}
inline bool is_operand(char sym) {
// is sym an operand?
return (sym >= 'a' && sym <= 'z');
}
void in_to_post(string & expr) {
// infix to postfix converter
// input: infix expression
stack< pair<char, short> > op_st; // operator stack
int len = expr.length();
for (int i = 0; i < len; ++i) {
if (is_operator(expr[i])) { // operator
// pop op_stack until the
// top of the stack has less or equal precedence
// than curr operator or stack is empty
while(1) {
if (op_st.empty()) { // stack is empty; straight away push
op_st.push(std::make_pair(expr[i], op_in_precedence(expr[i])));
break;
}
pair <char, short> & top_op = op_st.top();
if (top_op.second > op_out_precedence(expr[i])) {
cout << top_op.first;
op_st.pop();
}
else {
op_st.push(std::make_pair(expr[i], op_in_precedence(expr[i])));
break;
}
}
}
else if (is_operand(expr[i])) { // operand; push it to output queue immediately
cout << expr[i];
}
else if (expr[i] == ')') { // right paranthesis
while (1) {
if (op_st.empty()) { // invalid expression; ')' reached before matching '('
cout << "No matching '(' found\n";
abort();
}
pair <char, short> & top_op = op_st.top();
if (top_op.first == '(') { // matching '(' found; stop
op_st.pop();
break;
}
else {
cout << top_op.first;
op_st.pop();
}
}
}
}
// pop out the whole op_st (if any)
while (!(op_st.empty())) {
pair <char, short> & top_op = op_st.top();
cout << top_op.first;
op_st.pop();
}
}
int main() {
int t;
cin >> t;
for (int i = 0; i < t; ++i) {
string expr;
cin >> expr;
//cout << expr.length() << endl;
in_to_post(expr);
cout << "\n";
}
return 0;
}

parentheses balanced in C language [closed]

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 6 years ago.
Improve this question
This is a parentheses balanced code. I submitted and got comment from my professor.
"Your stack is supposed to grow and shrink dynamically to accommodate any number of characters. DO NOT USE scanf for %s, this is risky behavior and Dr. Adams does not approve. Write a helper function to read in characters until newline."
Can you help me to fix this problem?
Your professor is correct and he gave you the solution: do not read a line into a buffer with scanf("%s",...): an arbitrary long line will cause a buffer overflow. You do not need to read a full line, just make check_balanced read one character at a time:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "stack.h"
#define TRUE 1
#define FALSE 0
int check_matching(void);
int main(int argc, char *argv[]) {
int n, i, c;
/* get the number of cases */
if (scanf("%d", &n) != 1) {
printf("invalid number\n");
exit(1);
}
/* consume the rest of the line */
while ((c = getchar()) != EOF && c != '\n')
continue;
for (i = 0; i < n; i++) {
if (check_matching()) {
printf("yes\n");
} else {
printf("no\n");
}
}
return 0;
}
int check_matching(void) {
int ret = TRUE, symbol, checkSymbol;
LinkedStack *pStack;
StackNode *pNode;
StackNode node;
pStack = createLinkedStack();
if (pStack == NULL) {
printf("createLinkedStack failed\n");
exit(1);
}
/* read a full line, one byte at a time */
while ((symbol = getchar()) != EOF && symbol != '\n') {
if (ret == FALSE)
continue;
switch (symbol) {
case '(':
case '[':
case '{':
node.data = symbol;
pushLS(pStack, node);
break;
case ')':
case ']':
case '}':
pNode = popLS(pStack);
if (pNode == NULL) {
ret = FALSE;
break;
} else {
checkSymbol = pNode->data;
if ((symbol == ')' && checkSymbol == '(')
|| (symbol == ']' && checkSymbol == '[')
|| (symbol == '}' && checkSymbol == '{')) {
// Right case. do nothing.
} else {
ret = FALSE;
}
free(pNode);
}
break;
}
}
if (isLinkedStackEmpty(pStack) == FALSE) {
ret = FALSE;
}
deleteLinkedStack(pStack);
return ret;
}

Why my program terminates (using pipes)?

I want to make a shell that can use pipes. When I use this code to run a pipe in my shell even though everything is in a WHILE(1) loop my shell terminates. Why? Is there a problem with the use of the dup function?
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdbool.h>
int main(void)
{
int pfds[2];
pipe(pfds);
char *ar1;
const char sp = ' ';
int temp, temp1, temp2, acc;
int i, j;
int t = 0;
char *line=(char *) malloc(1024*sizeof(char));
char *frsarg=(char *) malloc(1024*sizeof(char));
char *firstcmd=(char *) malloc(1024*sizeof(char));
char *seccmd=(char *) malloc(1024*sizeof(char));
char *scmd=(char *) malloc(1024*sizeof(char));
char *secondcmd=(char *) malloc(1024*sizeof(char));
char *secarg=(char *) malloc(1024*sizeof(char));
char *frscmd=(char *) malloc(1024*sizeof(char));
char *cmd1=(char *) malloc(1024*sizeof(char));
char *cmd=(char *) malloc(1024*sizeof(char));
char *cmdf=(char *) malloc(1024*sizeof(char));
char *arg1=(char *) malloc(1024*sizeof(char));
char *allarg=(char *) malloc(1024*sizeof(char));
char *arg2=(char *) malloc(1024*sizeof(char));
char *arg3=(char *) malloc(1024*sizeof(char));
while (1) {
/* Ektypwse to command prompt */
printf("$ ");
fflush(stdout);
fgets(line, 1024, stdin); //Reads the command.
for(i=0;i<1024;i++){
if(line[i]=='\n') //Deletes the "Enter" from the end of the string.
{
line[i]='\0'; //Replace "Enter" with \0.
}
if(line[i] == 'e' && line[i+1] == 'x' && line[i+2] == 'i' && line[i+3] == 't' ) {
exit(1);
}
}
seccmd = strchr(line, '|');
acc = 0;
for(i=0;i<1024;i++){
if(line[i]=='|'){
acc = i;
t=t+1;
} //Finds the second space.
}
/*FIRST COMMAND AND ARGUMENT*/
if(acc != 0 ){
//printf("OKIF\n");
for(j=0;j<acc;j++){
//printf("OKFOR\n");
frscmd[j]= line[j];
}
//printf("FIRST COMMAND %s\n", frscmd);
}
/*FIRST ARG*/
frsarg = strchr(frscmd, sp);
if(frsarg != NULL){
while(isspace(*frsarg)) ++frsarg;
}
for (i=0;i<1024;i++){
if (frsarg[i] == ' '){
frsarg[i] = '\0';
}
}
/*FIRST COMMAND*/
acc = 0;
for(i=0;i<1024;i++){
if(frscmd[i]==' '){
acc = i;
break;
}
}
if(acc != 0 ){
//printf("OKIF\n");
for(j=0;j<acc;j++){
//printf("OKFOR\n");
firstcmd[j]= frscmd[j];
}
}
if(firstcmd != NULL){
while(isspace(*firstcmd)) ++firstcmd;
}
printf("FIRST COMMAND TEST %s TEST\n", firstcmd);
printf("FIRST ARGUMENT TEST %s TEST\n", frsarg);
// firstcmd == "ls" ,frsarg == "-l"
/*SECOND COMMAND AND ARGUMENTS */
//seccmd = " | ws -l
//SECOND COMMAND WITHOUT "|" secondcmd = _wc_-l
secondcmd = strchr(seccmd, sp);
if(secondcmd != NULL){
while(isspace(*secondcmd)) ++secondcmd;
}
//SECCOND COMMAND scmd
acc = 0;
for(i=0;i<1024;i++){
if(secondcmd[i]==' '){
acc = i+1;
}
}
if(acc != 0 ){
for(j=0;j<acc;j++){
scmd[j]= secondcmd[j];
}
}
for (i=0;i<1024;i++){
if (scmd[i] == ' '){
scmd[i] = '\0';
}
}
printf("SECOND COMMAND TEST %s TEST\n", scmd);
//SECOND ARGUMENT secarg
secarg = strchr(secondcmd, sp);
if(secarg != NULL){
while(isspace(*secarg)) ++secarg;
}
printf("SECOND ARGUMENT TEST %s TEST\n", secarg);
//FIRST COMMAND = firstcmd____FIRST ARGUMENT = frsarg_____SECOND COMMAND = scmd_____SECOND ARGUMENT = secarg
if (!fork()) {
close(1); /* close normal stdout */
dup(pfds[1]); /* make stdout same as pfds[1] */
close(pfds[0]); /* we don't need this */
execlp(firstcmd, firstcmd, frsarg,(char*) NULL);
} else {
close(0); /* close normal stdin */
dup(pfds[0]); /* make stdin same as pfds[0] */
close(pfds[1]); /* we don't need this */
execlp(scmd, scmd, secarg,(char*) NULL);
}
return 0;
}
}
Well, this is a very long and complex piece of code, and the logic seems
rather ad hoc. It would take me way too long to dissect the whole
thing.
I do observe that you fork() only once, and each branch then calls
execlp() to run one of the two processes in your pipeline. That leaves
no process continuing to run the shell. So you really need to fork()
twice.
Let's say that the original process is A. After the first call to
fork() we have original process A and child A1. A then calls
wait() to pause until A1 terminates. A1 calls fork() again and
runs the pipelined commands.
Or something like that. Looking at my code bank, I see the last time I
experimented with this stuff was in 2000, and I wasn't doing two
subprocesses as you are. But this should be a step in the right
direction, anyway.

using sscanf(), read string to array of int?

i have this string:
12 4 the quick 99 -1 fox dog \
what i want in my program:
myArray[] = {12, 4, 99, -1};
how i do a multiple number scanning?
See my answer to your other question here. It's a relatively simple matter to replace the strtok section to recognize non-numeric words and neither increment the count (in the first pass) nor load them into the array (in the second pass).
The code has changed as follows:
Using an input file of:
12 3 45 6 7 8
3 5 6 7
7 0 -1 4 5
12 4 the quick 99 -1 fox dog \
it produces output along the lines of:
0x8e42170, size = 6:
12 3 45 6 7 8
0x8e421d0, size = 4:
3 5 6 7
0x8e421e0, size = 5:
7 0 -1 4 5
0x8e42278, size = 4:
12 4 99 -1
Here's the code that produced that output:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <errno.h>
// This is the linked list of integer arrays.
typedef struct _tIntArray {
int size;
int *array;
struct _tIntArray *next;
} tIntArray;
static tIntArray *first = NULL;
static tIntArray *last = NULL;
// Check that argument is numeric, optional minus sign followed by
// zero or more digits (you may want one or more).
static int isAllNumeric (char *word) {
char *s = word;
if (*s == '-')
s++;
for (; *s != '\0'; s++)
if ((*s < '0') || (*s > '9'))
return 0;
return 1;
}
// Add a line of integers as a node.
static int addNode (char *str) {
tIntArray *curr; // pointers for new integer array.
char *word; // word within string.
char *tmpStr; // temp copy of buffer.
int fldCnt; // field count for line.
int i;
// Count number of fields.
if ((tmpStr = strdup (str)) == NULL) {
printf ("Cannot allocate duplicate string (%d).\n", errno);
return 1;
}
fldCnt = 0;
for (word = strtok (tmpStr, " "); word; word = strtok (NULL, " "))
if (isAllNumeric (word))
fldCnt++;
free (tmpStr);
// Create new linked list node.
if ((curr = malloc (sizeof (tIntArray))) == NULL) {
printf ("Cannot allocate integer array node (%d).\n", errno);
return 1;
}
curr->size = fldCnt;
if ((curr->array = malloc (fldCnt * sizeof (int))) == NULL) {
printf ("Cannot allocate integer array (%d).\n", errno);
free (curr);
return 1;
}
curr->next = NULL;
for (i = 0, word = strtok (str, " "); word; word = strtok (NULL, " "))
if (isAllNumeric (word))
curr->array[i++] = atoi (word);
if (last == NULL)
first = last = curr;
else {
last->next = curr;
last = curr;
}
return 0;
}
int main(void) {
int lineSz; // current line size.
char *buff; // buffer to hold line.
FILE *fin; // input file handle.
long offset; // offset for re-allocating line buffer.
tIntArray *curr; // pointers for new integer array.
int i;
// Open file.
if ((fin = fopen ("qq.in", "r")) == NULL) {
printf ("Cannot open qq.in, errno = %d\n", errno);
return 1;
}
// Allocate initial line.
lineSz = 2;
if ((buff = malloc (lineSz+1)) == NULL) {
printf ("Cannot allocate initial memory, errno = %d.\n", errno);
return 1;
}
// Loop forever.
while (1) {
// Save offset in case we need to re-read.
offset = ftell (fin);
// Get line, exit if end of file.
if (fgets (buff, lineSz, fin) == NULL)
break;
// If no newline, assume buffer wasn't big enough.
if (buff[strlen(buff)-1] != '\n') {
// Get bigger buffer and seek back to line start and retry.
free (buff);
lineSz += 3;
if ((buff = malloc (lineSz+1)) == NULL) {
printf ("Cannot allocate extra memory, errno = %d.\n", errno);
return 1;
}
if (fseek (fin, offset, SEEK_SET) != 0) {
printf ("Cannot seek, errno = %d.\n", errno);
return 1;
}
continue;
}
// Remove newline and process.
buff[strlen(buff)-1] = '\0';
if (addNode (buff) != 0)
return 1;
}
// Dump table for debugging.
for (curr = first; curr != NULL; curr = curr->next) {
printf ("%p, size = %d:\n ", curr, curr->size);
for (i = 0; i < curr->size; i++)
printf (" %d", curr->array[i]);
printf ("\n");
}
// Free resources and exit.
free (buff);
fclose (fin);
return 0;
}

Resources