I'm trying to upgrade a Bada app from 1.2 to 2.0 with no experience of Bada. I have the project building and can run it in the emulator but I get a load of warnings and I cant click the text boxes to get a keyboard and enter anything in the emulator.
Unfortunately the warning messages are completely cryptic to me, for example
SearchForm::SearchForm(void) :
gives the warning message "when initialized here"
What when initialized here??!!
Also, all the TryCatch statements show syntax error, and nothing I have found on the internet seems to make it happy:
result OnDraw()
{
result r = E_SUCCESS;
Canvas* readerCanvas = GetCanvasN();
TryCatch(E_SUCCESS == GetLastResult(), "Failed to get canvas: %S", GetErrorMessage(r));
if (readerCanvas)
{
Rectangle tempRect(0, 0, GetBounds().width, GetBounds().height);
Point tempPoint(0, 0);
r = readerCanvas->Copy(tempPoint, *iDrawingCanvas, tempRect);
TryCatch(E_SUCCESS == r, "Failed to copy canvas: %S", GetErrorMessage(r));
delete readerCanvas;
}
return r;
CATCH:
delete readerCanvas;
return r;
}
The TryCatch line says "statement has no effect", if I try edit it to match the examples I'v found I get a syntax error.
What's up with this?
It seems like you are trying to outdo your IDE's supposed bad messages by quoting them entirely out of context and only partially. Let me break it down:
TryCatch
The macro is defined as
TryCatch(condition, cleanup, message)
When the condition is evaluated to false, this will goto CATCH. You could think of the macro like this:
if (!condition)
{
goto CATCH;
}
For example, you can use it like this:
void TryCatchDemo::UseTryCatch(void)
{
TryCatch(1==2, , "1 is NOT 2");
AppLog("This should not appear");
CATCH:
AppLog("Catch block");
}
Now, your second parameter is a string literal, "Failed to get canvas: %S", which unsurprisingly, doesn't have an effect when used as statement:
"does nothing";
123; // just like this
So the compiler is being nice to warn you of the fact that you probably had something else in mind. Note also, that statement has no effect is not a syntax error.
"when initialized here"
Know your language! The code quoted isn't legal C++ to begin with:
SearchForm::SearchForm(void) :
At best this is the beginning of a constructor definition, with a missing initializer list and body. In the C++ language spec, class members are initialized in the order in which they were declared, not in the order in which they appear in the initializer list. A minimal example:
struct X
{
int a, b;
X() : b(), a() {}
};
This results in the compiler warning:
/tmp/test.cpp|3 col 13| warning: ‘X::b’ will be initialized after [-Wreorder]
/tmp/test.cpp|3 col 10| warning: ‘int X::a’ [-Wreorder]
/tmp/test.cpp|4 col 6| warning: when initialized here [-Wreorder]
As you can see, you not only clipped the code but also the warnings! If you read the whole message and the whole code, the fix would be pretty obvious:
struct X
{
int a, b;
X() : a(), b() {}
};
Bonus: In case you were wondering, why the ordering matters, consider what happens when you do:
struct X
{
int a, b;
X() : b(), a(b) {} // OOPS!
};
Hope this helps
Using a Format String with the Macros
Edit I just noted this: it is probably not supported to use format strings inside the Try/Catch macros:
Each of the macros that support a message parameters actually support format strings. A format string is similar to the format string of printf on systems that support it (bada does NOT support it)
Related
I wrote a function that requires two parameters, but I don't want those two parameters to be 0.
I want to make the compiler know that those two parameters cannot be 0 through some ways, otherwise the editor will report an error in the form of "red wavy line".
I refer to "custom exception class" to solve this problem, but I find this method does not work.
If there are someone knows how to do , I will be very happy, because it takes me a whole day
For example:
#include<iostream>
using namespace std;
int Fuction(int i , int j){
//code
}
int main(){
Funciton(1,1);
Funciton(0,0);
//I don't want i or j is zero
//But if they are still zero , The program will still work normally
return 0;
}
There is no integer type without a 0. However, you can provoke a compiler error by introducing a conversion to a pointer type. Its a bit hacky, but achieves what you want (I think) for a literal 0:
#include <iostream>
struct from_int {
int value;
from_int(int value) : value(value) {}
};
struct non_zero {
int value;
non_zero(int*) = delete;
non_zero(from_int f) : value(f.value) {}
};
void bar(non_zero n) {
int i = n.value; // cannot be 0
}
int main() {
bar(non_zero(42));
//bar(non_zero(0)); // compiler error
}
bar is the function that cannot be called with a 0 parameter. 0 can be converted to a pointer but that constructor has no definition. Any other int will pick the other constructor. Though it requires the caller to explicitly construct a non_zero because only one user defined conversion is taken into account.
Note that this only works for a literal 0. There is no error when you pass a 0 to this function:
void moo(int x){
bar(non_zero(x));
}
Thats why it should be considered as a hack. Though, in general it is not possible to trigger a compiler error based on the value of x which is only known at runtime.
If you want to throw an exception, thats a whole different story. You'd simply add a check in the function:
if (i == 0) throw my_custom_exception{"some error message"};
If you are using only MSVC you can also take a look at Structured Annotation Language (SAL). It is described on MSDN.
For your case you might be interested in _In_range_(lb,ub). An example would be:
void f(_In_range_(1,300) int a, _In_range_(1, 2147483647) int b);
Please note that this will not prohibit calling f(0, 0) but code analysis will trigger a warning. That warning will be triggered also in cases where you call f(x,x) and the compiler knows that x is zero.
In the past I liked to use SAL as it makes the interface clearer and can help reveal errors because the compiler can check more semantics. But now with modern C++ und the CppCoreGuidelines I am trying to follow the guidelines and so normally I don't need SAL anymore.
I am using C++ in Visual Studio Code. When I want to initialise a variable I cannot initialise it with {} (e.g., int x {0};). Instead, I have to use () (e.g., int x (0);).
The error I get when using {} is "error: expected ';' at end of declaration" Although I have put ; at the end of declaration.
I'm using clang 11.0.0 as the compiler. Is it related to the compiler?
The code runs through the terminal by ./filename command. However, it gives errors when running by coderunner extension in VSCode.
In order to initialize a variable with {} you must say it is = {}.
Like this:
int x = {3}; //you wouldn't really do this for simple variable though I don't think since you can just say int x = 3;
//or if you are making a custom object you might say:
MyObject object = {"apples", 3, "red"};
// to set the variables inside the object. in the order they are declared.
I hope this answers your question!
In the following code, I'd expect that both references to System.Action type to be represented as a QualifiedNameSyntax but the second one is represented as a MemberAccessExpressionSyntax.
Is that correct? If so, why can't it be a QualifiedNameSyntax?
class Foo
{
public void M(object o)
{
var t = typeof(System.Action); // 1
switch(o)
{
case System.Action: // 2
break;
}
}
}
Generally you're only going to get a QualifiedNameSyntax in a Roslyn syntax tree where the only legal thing there is a qualified name; in those cases we're running a restricted parser that will only understand qualified names. Anything else we're running our generic expression parser which will spit out whatever expression is there, and we'll figure out what it actually is during binding. Because consider another case like:
SomeEnum e;
switch (e)
{
case SomeEnum.Blue: Console.WriteLine("Blue!"); return;
}
In that case the SomeEnum.Blue is absolutely an access to a member. But we don't actually know what "SomeEnum" is until binding, so we just always go with MemberAccessExpression.
I can't tell you why for sure, but here's one relevant thing to think about:
In legal code, I think you're right that a switch can never accept a MemberAccessExpression, and so a QualifiedNameSyntax would be sufficient to represent this.
However let's look at some illegal code, and see what happens:
class Foo
{
public static void M(object o)
{
var t = typeof(Foo.M(5)); // 1
switch(o)
{
case Foo.M(5): // 2
break;
}
}
}
This gives 4 errors for the first usage of Foo.M(5):
error CS1026: ) expected
error CS1002: ; expected
error CS1513: } expected
error CS0426: The type name 'M' does not exist in the type 'Foo'
And only 1 for the second:
error CS0426: The type name 'M' does not exist in the type 'Foo'
By allowing a more flexible grammar in the second case, error messages are much better, as they can be done at the semantic level rather than a syntax level.
Since switch expressions accept any pattern as a case, it's more likely that you'll write something invalid, so good error messages are more important in that case.
I have inherited a (large) piece of code which has an error tracking mechanism where they pass in a boolean variable to all the methods they call and on errors at various stages of execution the method is stopped and returns, sometimes a default value.
Something like (BEFORE):
#include <iostream.h>
int fun1(int par1, bool& psuccess)
{
if(par1 == 42) return 43;
psuccess = false;
return -1;
}
int funtoo(int a, bool& psuccess)
{
int t = fun1(a, psuccess);
if(!psuccess)
{
return -1;
}
return 42;
}
void funthree(int b, bool& psuccess)
{
int h = funtoo(b, psuccess);
if(!psuccess)
{
return;
}
cout << "Yuppi" << b;
}
int main()
{
bool success = true;
funthree(43, success);
if(!success)
{
cout<< "Life, universe and everything have no meaning";
}
}
Please note, that this is a mixture of C and C++ code, exactly the way the project is in.
Now, comes a piece of C magic: "someone" somewhere defined a macro:
#define SUCCES_OR_RETURN if(!psuccess) return
And the program above becomes (AFTER):
#include<iostream.h>
int fun1(int par1, bool& psuccess)
{
if(par1 == 42) return 43;
psuccess = false;
return -1;
}
int funtoo(int a, bool& psuccess)
{
int t = fun1(a, psuccess);
SUCCES_OR_RETURN -1;
return 42;
}
void funthree(int b, bool& psuccess)
{
int h = funtoo(b, psuccess);
SUCCES_OR_RETURN ;
std::cout << "Yuppi" << b;
}
int main()
{
bool success = true;
funthree(43, success);
if(!success)
{
cout<< "Life, universe and everything have no meaning";
}
}
The question: I am wondering if there is a nicer way to handle this kind of error tracking or I have to live with this. I personally don't like the abuse of the C macro SUCCES_OR_RETURN ie. that once it is called with a parameter, and in other cases it is called without, feels like a real return statement, but I did not find any better solutions to this ancient design.
Please note that due to platform restrictions we have several restrictions, but regardless of it I am willing to hear opinions about these two:
throwing exceptions. The code is a mixture of C and C++ functions calling each other and the compiler sort of does not support throw (accepts in the syntax but does nothing with it, just a warning). This solution is sort of the standard way of solving this problem in a C++ environment.
C++11 features, this goes to a tiny embedded platform with an obscure and ancient "almost" C++ compiler which wasn't made to support the latest C++ features. However for future reference I am curios if there is anything C++11 offers.
template magic. The compiler has problems understanding complex templated issues, but again I am willing to see any solutions that you can come up with.
Edit
Also, as #BlueMoon suggested in the commend, creating a global variable is not working since at a very beginning of the function chain calling the success variable is a member variable of a class, and there are several objects of this class created, each of them needs to report its success status :)
There's a great breakdown of hybrid C and C++ error handling strategies here:
http://blog.sduto.it/2014/05/a-c-error-handling-style-that-plays.html
To quote the linked article, your options largely boil down to:
Return an error code from functions that can fail.
Provide a function like Windows's GetLastError() or OpenGL's glGetError() to retrieve the most recently occurring error code.
Provide a global (well, hopefully, thread-local) variable containing the most recent error, like POSIX's errno.
Provide a function to return more information about an error, possibly in conjunction with one of the above approaches, like POSIX's strerror function.
Allow the client to register a callback when an error occurs, like GLFW's glfwSetErrorCallback.
Use an OS-specific mechanism like structured exception handling.
Write errors out to a log file, stderr, or somewhere else.
Just assert() or somehow else terminate the program when an error occurs.
It seems like the author of the code you have inherited picked a rather strange way, passing a pointer to a boolean [sic] for the function to work with seems rather unusual.
The article has some great examples, personally I like this style:
libfoo_widget_container_t container = NULL;
libfoo_error_details_t error = NULL;
if (libfoo_create_widgets(12, &container, &error) != libfoo_success) {
printf("Error creating widgets: %s\n", libfoo_error_details_c_str(error));
libfoo_error_details_free(error);
abort(); // goodbye, cruel world!
}
Here you get a bit of everything, passed in pointer to error type, a comparison against a success constant (rather than 0|1, a painful dichotomy between C and the rest of the world!).
I don't think it would be too much of a push to say that your macro could rather better be implemented with a goto, in any case, if a function is calling SUCCES_OR_RETURN more than once, it might be a clue that the function is doing too much. Complex cleanup, or return might be a code smell, you can read more here http://eli.thegreenplace.net/2009/04/27/using-goto-for-error-handling-in-c/
I have seen this style of error handling before. I call it error-oblivious manual pseudo-exceptions.
The code flow is mostly error-oblivious: you can call 3 functions in a row with the same error flag, then look at the error flag to see if any errors have occurred.
The error flag acts as a pseudo-exception, where once set we start "skipping" over normal code flow, but this is done manually instead of automatically.
If you do something and do not care if an error occurs, you can just drop the error produced and proceed on.
The ICU library handles errors in a similar way.
A more C++1y way to do this while minimizing structural differences would be to modify code to return an expected object.
An expected<T, Err> is expected to be a T, and if something went wrong it is instead an Err type. This can be implemented as a hybrid of boost::variant and C++1y's std::optional. If you go and overload most arithmetic operations on expected< T, Err > + U to return expected< decltype( std::declval<T&>() + std::declval<U>(), Err > and did some careful auto, you could allow at least arithmetic expressions to keep their structure. You'd then check for the error after the fact.
On the other hand, if the error return values are predictable based on their type, you could create a type that when cast to a given type produced an error value. Modify functions returning void to return an error object of some kind while you are at it. And now every function can
if (berror) return error_flag_value{};
which at least gets rid of that strange ; or -1; issue.
If you want to go full C++, the answer would be changing the "invalid return values" for exceptions...
#include <iostream>
#include <exception>
using std::exception;
struct error : exception { const char* what() const throw() override { return "unsuccessful"; } };
int fun1(int par1) {
if( par1 == 42 ) return 43;
throw error();
}
int funtoo(int a) {
fun1(a);
return 42;
}
void funthree(int b) {
funtoo(b);
std::cout << "Yuppi " << b << "\n";
}
int main() {
try {
funthree(42);
} catch(exception& e) {
std::cout << "Life has no meaning, because " << e.what() << "\n";
}
}
This prints Yuppi 42 (if you change the call funthree(42) for funthree(43) it prints Life has no meaning, because unsuccessful...)
(live at coliru)
There's C4172 Visual C++ warning for cases when a function returns an address of a local or temporary or a reference to a local variable.
Something like this:
int& fun()
{
int var;
return var; //C4172
}
Now looks like it is a good idea to use #pragma warning to make Visual C++ treat C4172 as error and break compilation.
Are there any sane scenarios where C4172 is not actually an error?
I'm not sure why anyone would ever want to do this:
int * stackTester()
{
int dummy;
return &dummy;
}
bool stackGoesUp()
{
int dummy;
return stackTester() > &dummy;
}
But generally speaking, you should treat the warning like an error.
It is a level 1 warning, very hard to ignore. But the compiler is following language standards here, invoking UB is not forbidden. And it is a very common bug that too often does come to a good end. The pointed-to stack location stays stable as long as you don't make any function calls.
The best way to deal with this is to always turn warnings into errors. Compile with /WX, "Treat warnings as errors" setting in the IDE. If you then intentionally want to suppress a warning then #pragma warning makes it clear to everybody that something fishy is going on that was thought about and not an accident.
Unused code
class base
{
virtual blah& makeBlah()
}
class red : public base
{
blah& makeBlah() { return blah(); } // there are no red blahs, never called
}
class blue : public base
{
blah& makeBlah() { actual code to make a blah }
}