scanf_s throws exception - windows

Why does the following code throw an exception when getting to the second scanf_s after entering an number to put into the struct.
This by no means represents a complete linked list implementation.
Not sure how to get onto the next scanf_s when having entered the value? Any ideas?
EDIT: Updated code with suggested solution, but still get an AccessViolationException after first scanf_s
Code:
struct node
{
char name[20];
int age;
float height;
node *nxt;
};
int FillInLinkedList(node* temp)
{
int result;
temp = new node;
printf("Please enter name of the person");
result = scanf_s("%s", temp->name);
printf("Please enter persons age");
result = scanf_s("%d", &temp->age); // Exception here...
printf("Please enter persons height");
result = scanf_s("%f", &temp->height);
temp->nxt = NULL;
if (result >0)
return 1;
else return 0;
}
// calling code
int main(array<System::String ^> ^args)
{
node temp;
FillInLinkedList(&temp);
...

You are using scanf_s with incorrect parameters. Take a look at the examples in the MSDN documentation for the function. It requires that you pass in the size of the buffer after the buffer for all string or character parameters. So
result = scanf_s("%s", temp->name);
should be:
result = scanf_s("%s", temp->name, 20);
The first call to scanf_s is reading garbage off the stack because it is looking for another parameter and possibly corrupting memory.
There is no compiler error because scanf_s uses a variable argument list - the function doesn't have a fixed number of parameters so the compiler has no idea what scanf_s is expecting.

You need
result = scanf_s("%d", &temp->age);
and
result = scanf_s("%f", &temp->height);
Reason is that sscanf (and friends) requires a pointer to the output variable so it can store the result there.
BTW, you have a similar problem with the parameter temp of your function. Since you're changing the pointer (and not just the contents of what it points to), you need to pass a double pointer so that the changes will be visible outside your function:
int FillInLinkedList(node** temp)
And then of course you'll have to make the necessary changes inside the function.

scanf() stores data into variables, so you need to pass the address of the variable (or its pointer)Example:
char string[10];
int n;
scanf("%s", string); //string actually points to address of
//first element of string array
scanf("%d", &n); // &n is the address of the variable 'n'

%19c should be %s
temp->age should be &temp-age
temp->height should be &temp->height
Your compiler should be warning you
about these errors

I believe you need to pass parameters to scanf() functions by address. i.e. &temp->age
otherwise temp-age will be interpreted as a pointer, which will most likely crash your program.

Related

check an exception to call a C structure from go

I have a structure in C and I called that structure in my go program. If that structure throws any error it terminates my go program like below
orderbook.h
-------------
#ifndef _ORDERBOOK_H
#define _ORDERBOOK_H
typedef struct order order;
struct order {
int tradeid;
int side;
int symbol;
double amount;
double price;
};
orderbook.c
--------------
include "orderbook.h"
order* order_place(char *side,double amount,double price,char symbol[19])
{
struct order *tradeorder= calloc(1000000,sizeof(struct order));//Initlize the structure
//My internal code which place an order
clob_ord_t o=unxs_order(c, (clob_ord_t){CLOB_TYPE_LMT,parsed_side, amount, .lmt =price, .usr = (uintptr_t)out},NANPX);
if (o.qty.dis + o.qty.hid > 0.dd) {
/* put remainder of order into book */
i = clob_add(c, o);
//printf("orderid..%lu\n", i.usr);
printf("orderid..%s\n", i.usr);
insertMap(hashTable, i.usr, i);
// printMap(hashTable);
flag=true;
tradeorder[0].orderstatus=1;
tradeorder[0].orderid=offerid;
tradeorder[0].side=sid;
tradeorder[0].symbol=atoi(symbol);
tradeorder[0].amount=(double)o.qty.dis;
tradeorder[0].price=price;
}
return tradeorder; //return the structure
}
main.go
---------
o:=C.order_place(C.CString("ASK"),C.double(12.0),C.double(1.0),C.CString("1")) //this line may get an exception If some wrong parameter to pass otherwise returns correct value
If I put correct parameter to order_pace function from go there is no issue, If I pass some incorrect parameter then In get an exception an it terminates the go server. Now I need to handle that exception so that my server remain running irrespective of an exception.
You can't catch the fatal fault, and it isn't safe to continue after your C code throws a fault (unlike Go). The running program is in an undefined potentially dangerous state. The safest thing to do is shutdown the program and/or let it crash.
You must check for errors within C.order_place and return an error on failure. Eg, return NULL.
A few other recommendations:
Allocate struct order via Go to rely on the garbage collector to simplify memory management.
var order C.struct_order
C.order_place(&order, side, ...)
Always free strings allocated via C.CString once they are no longer needed.
cstr := C.CString("test")
C.free(unsafe.Pointer(cstr))
Depending on your platform, you can simplify debugging with improved stack traces by importing cgosymbolizer. This adds support for C stack traces.
import _ "github.com/ianlancetaylor/cgosymbolizer"
You probably should use char *symbol instead of char symbol[19] in your example since C.CString returns a pointer to an arbitrarily long C string, not a pointer to an array of 19 chars.

Why this is an infinite loop

i have declared a map below using stl and inserted some values in it.
#include<bits/stdc++.h>
int main()
{
map<int,int> m;
m[1]=1;
m[2]=1;
m[3]=1;
m[4]=1;
m[5]=1;
m[6]=1;
for(auto it=m.begin();it!=m.end();)
{
cout<<it->first<<" "<<it->second<<endl;
it=it++;
}
return 0;
}
When i executed the above written code it ended up in an infinite loop. Can someone tell me why it does so?
I am incrementing the value of iterator it and then it gets stored in it which should get incremented next time the loop is executed and eventually it should terminate normally.Am i wrong?
The bad line is it = it++;. It is undefined behavior! Because it is not defined, when it is increased, in your case it is increased before the assingment to itsself again, that the value of it before it is increased is assigned to it again and so it keeps at the first position. The correct line would be it = ++it; or only ++it;/it++;, because it changes itsself.
Edit
That is only undefined with the builtin types, but in here that is defined by the source-code of the map in the stl.
If you try doing something similar with an int, you'll get a warning:
int nums[] = { 1, 2, 3, 4, 5 };
for (int i = 0; i < sizeof nums / sizeof *nums; ) {
cout << nums[i] << '\n';
i = i++;
}
warning: operation on 'i' may be undefined [-Wsequence-point]
However, when you're using a class (std::map::iterator) which has operator overloading, the compiler probably isn't smart enought to detect this.
In other words, what you're doing is a sequence point violation, so the behavior is undefined behavior.
The post-increment operation would behave like this:
iterator operator ++ (int) {
auto copy = *this;
++*this;
return copy;
}
So, what happens to your increment step is that iterator it would get overwritten by the copy of its original value. If the map isn't empty, your loop would remain stuck on the first element.

C++ Ensuring that user input value is int only [duplicate]

This question already has answers here:
How to test whether stringstream operator>> has parsed a bad type and skip it
(5 answers)
Closed 8 years ago.
I am a little new to C++ and would really appreciate any input or suggestions! So with our intro course projects I have been looking for a way to ensure that when the prog. is asking for int values it correctly responds! That is it states its invalid in cases of both a double as well as string being entered! So if cin >> intVariable ... intVariable will not accept cin entry of "abdf" or 20.01.
So to achieve this I wrote the following function...It works but I am looking for your thoughts on how this process can be further improved!
void getIntegerOnly(int& intVariable, string coutStatement)
{
bool isInteger; // Check if value entered by user is int form or not
string tmpValue; // Variable to store temp value enetered by user
cout << coutStatement; // Output the msg for the cin statement
do
{
cin >> tmpValue; // Ask user to input their value
try // Use try to catch any exception caused by what user enetered
{
/* Ex. if user enters 20.01 then the if statement converts the
string to a form of int anf float to compare. that is int value
will be 20 and float will be 20.01. And if values do not match
then user input is not integer else it is. Keep looping untill
user enters a proper int value. Exception is 20 = 20.00 */
if (stoi(tmpValue) != stof(tmpValue))
{
isInteger = false; // Set to false!
clear_response(); // Clear response to state invalid
}
else
{
isInteger = true; //Set to true!
clear_cin(); // Clear cin to ignore all text and space in cin!
}
}
catch (...) // If the exception is trigured!
{
isInteger = false; // Set to false!
clear_response(); // Clear response to state invalid
}
} while (!isInteger); //Request user to input untill int clause met
//Store the int value to the variable passed by reference
intVariable = stoi(tmpValue);
}
This is simply an example of getting users age and age is greater than zero when running a Win32 console based application! Thank you for the feedback :)
One way would be something like the following:
std::string str;
std::cin >> str;
bool are_digits = std::all_of(
str.begin(), str.end(),
[](char c) { return isdigit(static_cast<unsigned char>(c)); }
);
return are_digits ? std::stoi(str) : throw std::invalid_argument{"Invalid input"};
and catch the exceptions on the calling side (stoi can also throw std::out_of_range).
You can leverage the second parameter of stoi().
string tmpValue;
size_t readChars;
stoi(tmpValue, &readChars);
if(readChars == tmpValue.length())
{
// input was integer
}
EDIT: this will not work for strings containing "." (for example integers passed in scientific notation).
This is not my work, but the answer to this question is what you want. Pass the string to it as a reference. It will return true is your string is an integer.
How do I check if a C++ string is an int?

Why is a temporary variable required in foreach to be included in lambda expression?

I was reading C# 4 in a Nutshell and I've come to this piece of code:
IQueryable<Product> SearchProducts (params string[] keywords)
{
IQueryable<Product> query = dataContext.Products;
foreach (string keyword in keywords)
{
string temp = keyword;
query = query.Where (p => p.Description.Contains (temp));
}
return query;
}
Right after the code there's a 'warning' that goes like this:
The temporary variable in the loop is required to avoid the outer variable trap, where the same variable is captured for each iteration of the foreach loop.
I don't get it, I don't understand why the temp variable is necessary. What is the outter variable trap?
From: http://www.albahari.com/nutshell/predicatebuilder.aspx
Can anybody please clarify this?
Because there is only one variable called keyword that is closed over. The temporary variable, however, is different each iteration.
Thus, without the temporary variable, when the lambda is executed later, keyword evaluates to the last value it was assigned in the loop.
Another solution, in some cases, is to force the evaluation (and end up with a List or such).
The problem is that keyword is changing. The => delegate closes on the current value of the variable, not the value it had back in the past when the delegate was created. There's a detailed explanation in Eric Lippert's blog post.
This classic C bug is the same mistake:
#include <stdio.h>
#include <pthread.h>
void * MyThreadFunction(void *x)
{
printf("I am thread %d\n", * (int *) x);
return NULL;
}
int main(void)
{
int i;
pthread_t t[10];
void *ret;
for(i=0; i<10; i++)
pthread_create(&t[i], NULL, MyThreadFunction, (void *) &i);
for(i=0; i<10; i++)
pthread_join(t[i], &ret);
}
The * (int *) x gets the current value of i, not the value when the thread was created.

How to solve access violation writing location error?

I have a simple program and I get access violation at *(str + start). Why? I should be able to change it. Right?
void fn()
{
char *str = "Hello wordl!";
int end = strlen(str);
int start = 0;
end--;
while(start < end)
{
*(str + start) = *(str + end); <--- Access violation writing location *(str + Start).
end--;
start++;
}
}
char *str = "Hello World"; is a const string, and cannot be modified. The compiler is free to put it into a non-writable location, resulting in the crash you see.
Replacing the declaration with char str[] = "Hello World"; should do what you want, putting the string into a modifiable array on the stack.
No, you should not. "Hello world" is a constant string literal, you need to allocate memory using malloc() in C, or new in C++ if you want memory you are free to modify.
As others have pointed out, literal strings may be stored in a read-only area of memory. Are you compiling with warnings turned on? You should get a warning about discarding the constness of the string literal.
What you can do instead is:
char *str = strdup("Hello, world!");
// Modify the string however you want
free(str);
It's because you're writing to a string literal's storage, which may be in a protected area of memory.
In your example, Hello wordl! is constant string, any attempt to modify this constant string will result in an exception.
Instead, You can do this -
string s = "Hello wordl!";
char* ptr = &s[0];
and then play around with ptr.

Resources