I don't understand why but the std::vector is not giving anything after i put a class pointer in the array.
// runs at start
void States::AssignState(GameState* state) {
_nextVacentState++;
_states.push_back(state);
}
// executes in a loop
void States::ExecuteCurrentState() {
// protection incase there is nothing in the array or the current state is not grater than the size of the array (not the problem after i nerrowed the problem down)
if (_nextVacentState == 0) std::cout << "Error: There is no states, setup some states then try again" << std::endl; return; // there is no states
if (_currentState >= _states.size() - 1) std::cout << "Error: Current State is grater than all possable states" << std::endl; return;
// The program just freezes at this and i can figure out why
_states[0]->tick();
std::printf("S");
}
This is one of the reasons I'd suggest getting in the habit of using curly braces for all if statements, even ones that live on a single line.
A problem line:
if (_nextVacentState == 0) std::cout << "Error: There is no states, setup some states then try again" << std::endl; return;
Let's add some newlines to make it clearer what's happening
if (_nextVacentState == 0)
std::cout << "Error: There is no states, setup some states then try again" << std::endl;
return;
That return statement is getting executed unconditionally, because only the first statement after if(_nextVacentState==0) is actually part of the if. So the compiler executes it as if it had been written like this:
if (_nextVacentState == 0)
{
std::cout << "Error: There is no states, setup some states then try again" << std::endl;
}
return;
But, what you want needs to be written like this instead:
if (_nextVacentState == 0)
{
std::cout << "Error: There is no states, setup some states then try again" << std::endl;
return;
}
You have same problem in the next if check for _currentState, as well.
Related
I've thought of following code by trying to solve a difficult 'nested-condition' problem:
goto error;
if (false)
{
error:
cout << "error block" << endl;
}
else
{
cout << "else block" << endl;
}
When I run this code, only error block is displayed, as expected (I guess?). But is this defined behavior across all compilers?
Yes, this is well defined. From stmt.goto#1
The goto statement unconditionally transfers control to the statement labeled by the identifier.
The identifier shall be a label located in the current function.
There are some restrictions, e.g. a case label cannot cross a non-trivial initialization
goto error;
int i = 42;
error: // error: crosses initialization of i
But these don't apply to your example. Also, in the case of crossing an initialization, this is a hard compiler error, so you don't have to worry about undefined behavior.
Note that once you jump to the case label error, you're effectively inside the true branch of the if condition, and it doesn't matter that you got there via a goto. So you're guaranteed that the else branch will not be executed.
My 5 cents:
If your compiler have optimizer, the code is reduced in following way:
// more code here
goto error; // this go directly to the label
if (false)
{
error:
cout << "error block" << endl;
// this skips else clause
}
else
{
cout << "else block" << endl;
}
// more code here
So the compiled code become just this:
// more code here
{
cout << "error block" << endl;
}
// more code here
Here is link to Godbolt:
https://gcc.godbolt.org/z/nY6E166Pz
(I did simplify the code a little bit so assembly is easier to read)
What is the difference between the output of event.window.windowID and SDL_GetWindowID()?
Why is it that std::cout << m_SDLEvent.window.windowID << std::endl;
outputs 1819558491 in console while std::cout << SDL_GetWindowID(m_SDLWindow) << std::endl; outputs 1 ?
How would I achieve getting the right ID of my SDL_Window* in the method below?
void InputManager::Update()
{
SDL_PollEvent(&m_SDLEvent);
switch (m_SDLEvent.type)
{
case SDL_QUIT:
std::cout << m_SDLEvent.window.windowID << std::endl;
SDL_HideWindow(SDL_GetWindowFromID(m_SDLEvent.window.windowID));
break;
}
}
You're seeing garbage window ID because you access an inactive union field. That's undefined behavior.
You can only access m_SDLEvent.window if m_SDLEvent.type == SDL_WINDOWEVENT.
But if m_SDLEvent.type == SDL_QUIT, you have to use m_SDLEvent.quit structure, which has no field for window id (because SDL_QUIT is not specific to a window, but means that the entire application should be closed).
Okay so HolyBlackCat's answer brought me to the right direction.
Instead of using SDL_QUIT (which is the quit event for the entire app, not one window) I should've checked for SDL_WINDOWEVENT_CLOSE which is an SDL_WINDOWEVENT which can be received by m_SDLEvent.window.event instead of m_SDLEvent.type
So the code now looks like this:
void InputManager::Update()
{
SDL_PollEvent(&m_SDLEvent);
if (m_SDLEvent.type == SDL_WINDOWEVENT)
{
switch (m_SDLEvent.window.event)
{
case SDL_WINDOWEVENT_CLOSE:
std::cout << m_SDLEvent.window.windowID << std::endl;
SDL_HideWindow(SDL_GetWindowFromID(m_SDLEvent.window.windowID));
break;
}
}
}
Now std::cout << m_SDLEvent.window.windowID << std::endl; outputs the correct ID.
ok, so im kinda new to C++ and im trying to build a basic login program. iv got it to work except for one problem... this is what iv got
void InitialLogin()
{
cout << "\t\t ===========LOGIN==========" << endl;
cout << "\t\n\n\n\tUsername/>> " ;
getline(cin, sUsername);
cout << "\t\n\tPassword/>> ";
getline(cin, sPassword);
if (sUsername == "myname" && sPassword == "mypass")
{
cout << "\n\t\t\t--ACCESS GRANTED--";
system("CLS");
}
else if (sUsername != "myname" && sPassword != "mypass")
{
SetConsoleTextAttribute(h, FOREGROUND_RED);
cout << "\n\t\t\t--ACCESS DENIED--\n\n\n";
SetConsoleTextAttribute(h, FOREGROUND_GREEN | FOREGROUND_INTENSITY);
main();
}
}
after i run this, if the login was successfull i have the following run after the screen is cleard...
void Initialization()
{
cout << "/>> Aquireing file list......" << endl;
cout << "/>> file list aquired........" << endl;
cout << "/>> determing file location.." << endl;
}
now my problem is, if i get the username or password wrong say once i get the initialization output twice, if i get it wrong twice, the output is three times.
i need to know how to clear the overflow or buffer or something...
please help :)
Your function is attempting to call main(). This is not legal C++.
You should return a status to see if the login worked or not. Then just loop until the status either becomes "true", or the user has run out of chances. Here is a small example:
bool InitialLogin();
int main()
{
int numChances = 3;
int numCount = 0;
bool loginOk = false;
while (numCount < numChances && !loginOk )
{
loginOk = InitialiLogin();
++numCount;
}
if ( !loginOk )
{
// number of chances ran out
return 0;
}
else
{
// proceed. Login was successful
}
}
bool InitialLogin()
{
//...
if (sUsername == "myname" && sPassword == "mypass")
{
//...
return true;
}
// anything here means that the login failed. There is no need for an if()
//...
return false;
}
I feel you are getting this because you are calling the main() function when both the password and username are incorrect (As a side note you might want to change the && in this check to || as you want access to be denied if either the password or username are incorrect).
You might want to consider getting the InitialLogin() function to return a bool to show weather the login was successful or not. If not the get it to run InitialLogin() again if successful then get it to proceed with the code.
In the place where you call InitialLogin() you can use a while loop to get it to repeat.
while(!InitialLogin()){}
So when InitialLogin() is not false (bad login) it will try again and when it is not true (good login) it will continue onto next section of code.
I'm currently writing a web-crawler/spider in C++ on Linux and I'm having some problems with updating a database. I'm fairly new to C/C++, just FYI.
The database updates are executed by a seperate thread (using pthreads) but the same problem exists if executed in main() so I, perhaps naively, discarded the threading stuff as the cause of anything.
I'm using libmysqlcppconn for the database API.
I am compiling with gcc version 4.4.3 (Ubuntu 4.4.3-4ubuntu5.1) with -O2 -Wall -pedantic and it compiles cleanly.
Nevertheless, when the function commitChangesToDatabase() below is called, it basically picks out items from a std::map (url_queue), throws them in a std::vector (updates) and erases said item from the original std::map, then proceeds to iterate over the std::vector, executing a MySQL prepared statement for each item in the vector. Here is where it fails hard.
It randomly either:
Crashes without any error output (no segfault, no stacktrace, no nothing)
Crashes with a glibc memory corruption detected (see output here: http://pastie.org/private/wlkuorivq5tptlcr7ojg)
Reports that the MySQL server has gone away (caught exception), but keeps trying (doesn't crash)
I have tried switching the prepared statement to a simple executeUpdate(), but to no avail.
I have tried eliminating the step with picking out items and rather just execute the updates whenever I find an item to update, in the first loop over url_queue.
Other functions in this application uses prepared statements as well (another UPDATE) and that works fine. Those functions are also run by seperate threads.
I would run the application through valgrind, but quite frankly, I don't understand most of the output so it wouldn't help me much - but if anyone wants the output from it, let me know which options to run it with and I'll provide it.
I have no clue how to proceed from here. Anyone have a clue what's wrong?
struct queue_item_t {
int id;
int sites_id;
int priority;
int depth;
int handler;
int state; // 0 = Pending, 1 = Working, 2 = Completed, 3 = Checked
double time_allowed_crawl;
bool status;
bool was_redirected;
double time;
double time_end;
double time_curl;
double size;
std::string hash;
std::string url;
std::string file;
std::string host;
};
void commitChangesToDatabase()
{
map< string, queue_item_t >::iterator it, end;
sql::PreparedStatement *pstmt;
int i = 0;
if (!url_queue.size()) {
return;
}
pthread_mutex_lock(&dbCommitMutex);
pthread_mutex_lock(&itemMutex);
cout << "commitChangesToDatabase()" << endl;
pstmt = dbPrepareStatement("UPDATE crawler_queue SET process_hash = NULL, date_crawled = NOW(), url = ?, hash = ? WHERE id = ?");
for (it = url_queue.begin(); it != url_queue.end();)
{
if (it->second.state == 2)
{
pstmt->setString(1, it->second.url);
pstmt->setString(2, it->second.hash);
pstmt->setInt(3, it->second.id);
try {
pstmt->executeUpdate();
++i;
} catch (sql::SQLException &e) {
cerr << "# ERR: SQLException in " << __FILE__;
cerr << "(" << __FUNCTION__ << ") on line " << __LINE__ << endl;
cerr << "# ERR: " << e.what();
cerr << " (MySQL error code: " << e.getErrorCode();
cerr << ", SQLState: " << e.getSQLState() << " )" << endl;
}
url_queue.erase(it++);
}
else {
++it;
}
}
delete pstmt;
cout << "~commitChangesToDatabase()" << endl;
pthread_mutex_unlock(&itemMutex);
pthread_mutex_unlock(&dbCommitMutex);
}
// this function is defined in another file but is written here just to show the contents of it
sql::PreparedStatement *dbPrepareStatement(const std::string &query)
{
return con->prepareStatement(query);
}
Edit:
Some seem to believe the problem is with the iteration over the url_queue collection, however I have ruled that out but commenting out everything that operates on the database, but not the iteration. Furthermore, the iteration here is a simplified (but working) version of the original which picks out items from the map, throws in a vector and erases from the map, as demonstrated below, and that part of the program works fine - it only crashes whenever the database is used.
for (it = url_queue.begin(); it != url_queue.end();)
{
if (it->second.state == 2)
{
update_item.type = (!it->second.was_redirected ? 1 : 2);
update_item.item = it->second;
updates.push_back(update_item);
url_queue.erase(it++);
}
else {
++it;
}
}
Edit 2:
Output from valgrind --leak-check=yes: http://pastie.org/private/2ypk0bmawwsqva3ikfazw
It seems, the iterator is incremented unnecessarily; first in loop body, and also in for statement. In this code, it is possible to increment the end iterator, this is a problematic operation and might be source of the problem.
The following loop structure is more suitable for this case:
it = url_queue.begin();
while( it != url_queue.end() ){
//loop body
}
I don't think it is a good idea to mess with iterators. replace:
else {
++it;
}
by:
else continue;
or just remove it.
I'm modifying the stock quoter example from the wustl CORBA release. The assignment is to implement a reply handler for the StockFactory class that handles calls to get_stock()
Here's my FactoryHandler implementation:
FactoryHandler_i.h:
#ifndef TAO_TUTORIALS_QUOTER_AMI_CLIENT_FACTORYHANDLER_I_H
#define TAO_TUTORIALS_QUOTER_AMI_CLIENT_FACTORYHANDLER_I_H
#include "QuoterS.h"
class Stock_Factory_Handler_i : public POA_Quoter::AMI_Stock_FactoryHandler
{
public:
Stock_Factory_Handler_i (int *response_count, ::Quoter::Stock_var& result);
void get_stock (::Quoter::Stock_ptr ami_return_val);
void get_stock_excep (::Messaging::ExceptionHolder * excep_holder);
private:
int *response_count_;
::Quoter::Stock_var& result_;
};
#endif /* TAO_TUTORIALS_QUOTER_AMI_CLIENT_HANDLER_I_H */
FactoryHandler_i.cpp:
#include "FactoryHandler_i.h"
#include "ace/streams.h"
Stock_Factory_Handler_i::
Stock_Factory_Handler_i (int *response_count, ::Quoter::Stock_var& result)
: response_count_ (response_count), result_ (result)
{
}
void
Stock_Factory_Handler_i::get_stock (::Quoter::Stock_ptr ami_return_val)
{
cout << "storing result" << endl;
result_ = ami_return_val;
(*this->response_count_)++;
}
void
Stock_Factory_Handler_i::get_stock_excep (::Messaging::ExceptionHolder * excep_holder)
{
// We ignore the exception, but this counts as a response, otherwise
// the application would not finish.
cerr << "Exception raised while getting stock"
<< endl;
(*this->response_count_)++;
}
And the client.cpp, from just before the part where changes have been made:
// ...
// Create and activate the handler...
int response_count = 0;
Single_Query_Stock_Handler_i handler_i (&response_count);
Quoter::AMI_Single_Query_StockHandler_var handler =
handler_i._this ();
// Create and activate the factory handler...
Quoter::Stock_var result;
Stock_Factory_Handler_i factory_handler_i (&response_count, result);
Quoter::AMI_Stock_FactoryHandler_var factory_handler =
factory_handler_i._this();
// Send all the requests, careful with error handling
int request_count = 0;
for (int i = 2; i != argc+1; ++i) {
try {
// Get the stock object
cout << "looking up stock symbol " << argv[i] << endl;
factory->sendc_get_stock (factory_handler.in (), argv[i]);
sleep(3); // wait for a response
cout << "converting result" << endl;
Quoter::Single_Query_Stock_var stock =
Quoter::Single_Query_Stock::_narrow (result.in ());
cout << "checking result" << endl;
CORBA::Any any;
any <<= stock;
CORBA::TypeCode_var tc = any.type();
cout << tc->kind() << endl;
if (CORBA::is_nil (stock.in ())) {
cerr << "Cannot get single query interface for <"
<< argv[i] << ">" << endl;
continue;
}
cout << "reading result" << endl;
stock->sendc_get_price_and_names (handler.in ());
request_count++;
}
catch (Quoter::Invalid_Stock_Symbol &) {
cerr << "Invalid stock symbol <"
<< argv[i] << ">" << endl;
}
}
while (response_count < 2 * request_count // multiply by 2 because both handlers increment response_count
&& orb->work_pending ()) {
orb->perform_work ();
}
// ...
When running the client, the output is:
looking up stock symbol MSFT
converting result
checking result
14
Cannot get single query interface for <MSFT>
(The 14 is the typecode for Stock, that's only for debugging)
Notably missing from the above is the "storing result" message that's supposed to be printed in the FactoryHandler's get_stock() callback method. I'm at a loss as to why, since the sendc_get_stock() method doesn't produce any (immediate) errors and is basically just a copy of the StockHandler's code, and from there it's the responsibility of the AMI/ORB interface to make the callback. But the original example (with a StockHandler only) works fine.
What am I doing wrong (and how do I fix it)?
EDIT: another bit of information: on the server side, StockFactory's get_stock() method does get called.
Sorry, I've no aswer for you. But a hint, ask your question at TOA's maling list at http://www.cs.wustl.edu/~schmidt/ACE-mail.html
HTH
I think that your problem is that work_pending returns true only if the ORB has immediate work to do, so it returns false in the time after your client sent his request and before the server sends his reply.
To validate that, simply remove the && orb->work_pending() condition from the loop, and use the version of perform_work that takes a timeout argument.