SQLite: consecutive invocation of finalize












1
















I have a function which aims to delete a concrete row from a SQLite database by an UID identifier.



The sequence is the following:

1. Create select query to check if the row exists

2. Prepare the query

3. Bind the row UID

4. Step

5. Finalize

If the row exist

{

6. Create delete query

7. Prepare it

8. Bind the UID

9. Step

10. Finalize

11. Finalize

}



As you can see first it checks if the row exist in order to notify the caller if the required UID is wrong, than it create new delete query.



The program works as expected in ~14/15 test cases. In the cases where the program is crashing it crashes to the last finalize invocation (11th point). I've checked all the data and it seems that everything is valid.



The question is what is the expected behaviour of consecutive invocation of finalize function. I tried to set 5 invocations of finalize one after another but the behaviour is the same.










share|improve this question


















  • 1





    I don't think I understand this correctly. Are you trying to finalize the same statement multiple times? You should only finalize it once. According to the documentation ( sqlite.org/c3ref/finalize.html ), it is "a grievous error" to use a prepared statement after having finalized, and I would assume that also applies to further finalize calls.

    – Blaze
    Nov 20 '18 at 10:26













  • In one particular case i have this two consecutive invocations of finalize. I also checked the documentation but thought that finalize would have any kind of protection. But now it seems to have some kind of undefined behaviour. That's why i created this question.

    – Георги Няголов
    Nov 20 '18 at 10:53






  • 2





    Well, it looks like there's protection for calling it on a NULL pointer ("harmless no-op"). I don't think there's such protection for invalid pointers, though, and I think the pointer becomes invalid after finalizing the statement once. The documentation mentions " undefined and undesirable behavior such as segfaults and heap corruption" - perhaps that's why it works only sometimes. You could also try checking the return statement of the second finalize call to see if it returns SQLITE_OK.

    – Blaze
    Nov 20 '18 at 11:01
















1
















I have a function which aims to delete a concrete row from a SQLite database by an UID identifier.



The sequence is the following:

1. Create select query to check if the row exists

2. Prepare the query

3. Bind the row UID

4. Step

5. Finalize

If the row exist

{

6. Create delete query

7. Prepare it

8. Bind the UID

9. Step

10. Finalize

11. Finalize

}



As you can see first it checks if the row exist in order to notify the caller if the required UID is wrong, than it create new delete query.



The program works as expected in ~14/15 test cases. In the cases where the program is crashing it crashes to the last finalize invocation (11th point). I've checked all the data and it seems that everything is valid.



The question is what is the expected behaviour of consecutive invocation of finalize function. I tried to set 5 invocations of finalize one after another but the behaviour is the same.










share|improve this question


















  • 1





    I don't think I understand this correctly. Are you trying to finalize the same statement multiple times? You should only finalize it once. According to the documentation ( sqlite.org/c3ref/finalize.html ), it is "a grievous error" to use a prepared statement after having finalized, and I would assume that also applies to further finalize calls.

    – Blaze
    Nov 20 '18 at 10:26













  • In one particular case i have this two consecutive invocations of finalize. I also checked the documentation but thought that finalize would have any kind of protection. But now it seems to have some kind of undefined behaviour. That's why i created this question.

    – Георги Няголов
    Nov 20 '18 at 10:53






  • 2





    Well, it looks like there's protection for calling it on a NULL pointer ("harmless no-op"). I don't think there's such protection for invalid pointers, though, and I think the pointer becomes invalid after finalizing the statement once. The documentation mentions " undefined and undesirable behavior such as segfaults and heap corruption" - perhaps that's why it works only sometimes. You could also try checking the return statement of the second finalize call to see if it returns SQLITE_OK.

    – Blaze
    Nov 20 '18 at 11:01














1












1








1









I have a function which aims to delete a concrete row from a SQLite database by an UID identifier.



The sequence is the following:

1. Create select query to check if the row exists

2. Prepare the query

3. Bind the row UID

4. Step

5. Finalize

If the row exist

{

6. Create delete query

7. Prepare it

8. Bind the UID

9. Step

10. Finalize

11. Finalize

}



As you can see first it checks if the row exist in order to notify the caller if the required UID is wrong, than it create new delete query.



The program works as expected in ~14/15 test cases. In the cases where the program is crashing it crashes to the last finalize invocation (11th point). I've checked all the data and it seems that everything is valid.



The question is what is the expected behaviour of consecutive invocation of finalize function. I tried to set 5 invocations of finalize one after another but the behaviour is the same.










share|improve this question















I have a function which aims to delete a concrete row from a SQLite database by an UID identifier.



The sequence is the following:

1. Create select query to check if the row exists

2. Prepare the query

3. Bind the row UID

4. Step

5. Finalize

If the row exist

{

6. Create delete query

7. Prepare it

8. Bind the UID

9. Step

10. Finalize

11. Finalize

}



As you can see first it checks if the row exist in order to notify the caller if the required UID is wrong, than it create new delete query.



The program works as expected in ~14/15 test cases. In the cases where the program is crashing it crashes to the last finalize invocation (11th point). I've checked all the data and it seems that everything is valid.



The question is what is the expected behaviour of consecutive invocation of finalize function. I tried to set 5 invocations of finalize one after another but the behaviour is the same.







c++ sqlite






share|improve this question













share|improve this question











share|improve this question




share|improve this question










asked Nov 20 '18 at 10:21









Георги НяголовГеорги Няголов

184




184








  • 1





    I don't think I understand this correctly. Are you trying to finalize the same statement multiple times? You should only finalize it once. According to the documentation ( sqlite.org/c3ref/finalize.html ), it is "a grievous error" to use a prepared statement after having finalized, and I would assume that also applies to further finalize calls.

    – Blaze
    Nov 20 '18 at 10:26













  • In one particular case i have this two consecutive invocations of finalize. I also checked the documentation but thought that finalize would have any kind of protection. But now it seems to have some kind of undefined behaviour. That's why i created this question.

    – Георги Няголов
    Nov 20 '18 at 10:53






  • 2





    Well, it looks like there's protection for calling it on a NULL pointer ("harmless no-op"). I don't think there's such protection for invalid pointers, though, and I think the pointer becomes invalid after finalizing the statement once. The documentation mentions " undefined and undesirable behavior such as segfaults and heap corruption" - perhaps that's why it works only sometimes. You could also try checking the return statement of the second finalize call to see if it returns SQLITE_OK.

    – Blaze
    Nov 20 '18 at 11:01














  • 1





    I don't think I understand this correctly. Are you trying to finalize the same statement multiple times? You should only finalize it once. According to the documentation ( sqlite.org/c3ref/finalize.html ), it is "a grievous error" to use a prepared statement after having finalized, and I would assume that also applies to further finalize calls.

    – Blaze
    Nov 20 '18 at 10:26













  • In one particular case i have this two consecutive invocations of finalize. I also checked the documentation but thought that finalize would have any kind of protection. But now it seems to have some kind of undefined behaviour. That's why i created this question.

    – Георги Няголов
    Nov 20 '18 at 10:53






  • 2





    Well, it looks like there's protection for calling it on a NULL pointer ("harmless no-op"). I don't think there's such protection for invalid pointers, though, and I think the pointer becomes invalid after finalizing the statement once. The documentation mentions " undefined and undesirable behavior such as segfaults and heap corruption" - perhaps that's why it works only sometimes. You could also try checking the return statement of the second finalize call to see if it returns SQLITE_OK.

    – Blaze
    Nov 20 '18 at 11:01








1




1





I don't think I understand this correctly. Are you trying to finalize the same statement multiple times? You should only finalize it once. According to the documentation ( sqlite.org/c3ref/finalize.html ), it is "a grievous error" to use a prepared statement after having finalized, and I would assume that also applies to further finalize calls.

– Blaze
Nov 20 '18 at 10:26







I don't think I understand this correctly. Are you trying to finalize the same statement multiple times? You should only finalize it once. According to the documentation ( sqlite.org/c3ref/finalize.html ), it is "a grievous error" to use a prepared statement after having finalized, and I would assume that also applies to further finalize calls.

– Blaze
Nov 20 '18 at 10:26















In one particular case i have this two consecutive invocations of finalize. I also checked the documentation but thought that finalize would have any kind of protection. But now it seems to have some kind of undefined behaviour. That's why i created this question.

– Георги Няголов
Nov 20 '18 at 10:53





In one particular case i have this two consecutive invocations of finalize. I also checked the documentation but thought that finalize would have any kind of protection. But now it seems to have some kind of undefined behaviour. That's why i created this question.

– Георги Няголов
Nov 20 '18 at 10:53




2




2





Well, it looks like there's protection for calling it on a NULL pointer ("harmless no-op"). I don't think there's such protection for invalid pointers, though, and I think the pointer becomes invalid after finalizing the statement once. The documentation mentions " undefined and undesirable behavior such as segfaults and heap corruption" - perhaps that's why it works only sometimes. You could also try checking the return statement of the second finalize call to see if it returns SQLITE_OK.

– Blaze
Nov 20 '18 at 11:01





Well, it looks like there's protection for calling it on a NULL pointer ("harmless no-op"). I don't think there's such protection for invalid pointers, though, and I think the pointer becomes invalid after finalizing the statement once. The documentation mentions " undefined and undesirable behavior such as segfaults and heap corruption" - perhaps that's why it works only sometimes. You could also try checking the return statement of the second finalize call to see if it returns SQLITE_OK.

– Blaze
Nov 20 '18 at 11:01












1 Answer
1






active

oldest

votes


















1














Though the documentation doesn't feel the need to state this explicitly, it's fairly obvious that what you're doing is "undefined behaviour" (within the scope of the library).



Much like deleteing dynamically allocated memory, you are supposed to finalize once. Not twice, not five times, but once. After you've finalized a prepared statement, it has been "deleted" and no longer exists. Any further operations on that prepared statement constitutes what the documentation calls "a grivous error" (if we presume that a superfluous call to finalize constitutes "use"; and why would we not?).



Fortunately there is no reason ever to want to do this. So, quite simply, don't! If your design is such that you've lost control of your code flow and, at the point of finalize, for some reason have insufficient information about your program's context to know whether the prepared statement has already been finalized, that's fine: much like we do with pointers, you can set it to nullptr so that subsequent calls are no-ops. But if you need to do this, you really should also revisit your design.



Why did it appear to work for you? Pure chance, much like with any other undefined behaviours:




Any use of a prepared statement after it has been finalized can result in undefined and undesirable behavior such as segfaults and heap corruption.




See also: "Why can't I close my car door twice without opening it?" and "Why can't I shave my imaginary beard?"






share|improve this answer
























  • Thank you all for the answers. It is obvious that i will redesign the code in order to remove this consecutive invocation of finalize. The reason of the question was to understand the problem clearly, which was achieved. Thanks again.

    – Георги Няголов
    Nov 20 '18 at 12:15











Your Answer






StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");

StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);

StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});

function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});


}
});














draft saved

draft discarded


















StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53390865%2fsqlite-consecutive-invocation-of-finalize%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown

























1 Answer
1






active

oldest

votes








1 Answer
1






active

oldest

votes









active

oldest

votes






active

oldest

votes









1














Though the documentation doesn't feel the need to state this explicitly, it's fairly obvious that what you're doing is "undefined behaviour" (within the scope of the library).



Much like deleteing dynamically allocated memory, you are supposed to finalize once. Not twice, not five times, but once. After you've finalized a prepared statement, it has been "deleted" and no longer exists. Any further operations on that prepared statement constitutes what the documentation calls "a grivous error" (if we presume that a superfluous call to finalize constitutes "use"; and why would we not?).



Fortunately there is no reason ever to want to do this. So, quite simply, don't! If your design is such that you've lost control of your code flow and, at the point of finalize, for some reason have insufficient information about your program's context to know whether the prepared statement has already been finalized, that's fine: much like we do with pointers, you can set it to nullptr so that subsequent calls are no-ops. But if you need to do this, you really should also revisit your design.



Why did it appear to work for you? Pure chance, much like with any other undefined behaviours:




Any use of a prepared statement after it has been finalized can result in undefined and undesirable behavior such as segfaults and heap corruption.




See also: "Why can't I close my car door twice without opening it?" and "Why can't I shave my imaginary beard?"






share|improve this answer
























  • Thank you all for the answers. It is obvious that i will redesign the code in order to remove this consecutive invocation of finalize. The reason of the question was to understand the problem clearly, which was achieved. Thanks again.

    – Георги Няголов
    Nov 20 '18 at 12:15
















1














Though the documentation doesn't feel the need to state this explicitly, it's fairly obvious that what you're doing is "undefined behaviour" (within the scope of the library).



Much like deleteing dynamically allocated memory, you are supposed to finalize once. Not twice, not five times, but once. After you've finalized a prepared statement, it has been "deleted" and no longer exists. Any further operations on that prepared statement constitutes what the documentation calls "a grivous error" (if we presume that a superfluous call to finalize constitutes "use"; and why would we not?).



Fortunately there is no reason ever to want to do this. So, quite simply, don't! If your design is such that you've lost control of your code flow and, at the point of finalize, for some reason have insufficient information about your program's context to know whether the prepared statement has already been finalized, that's fine: much like we do with pointers, you can set it to nullptr so that subsequent calls are no-ops. But if you need to do this, you really should also revisit your design.



Why did it appear to work for you? Pure chance, much like with any other undefined behaviours:




Any use of a prepared statement after it has been finalized can result in undefined and undesirable behavior such as segfaults and heap corruption.




See also: "Why can't I close my car door twice without opening it?" and "Why can't I shave my imaginary beard?"






share|improve this answer
























  • Thank you all for the answers. It is obvious that i will redesign the code in order to remove this consecutive invocation of finalize. The reason of the question was to understand the problem clearly, which was achieved. Thanks again.

    – Георги Няголов
    Nov 20 '18 at 12:15














1












1








1







Though the documentation doesn't feel the need to state this explicitly, it's fairly obvious that what you're doing is "undefined behaviour" (within the scope of the library).



Much like deleteing dynamically allocated memory, you are supposed to finalize once. Not twice, not five times, but once. After you've finalized a prepared statement, it has been "deleted" and no longer exists. Any further operations on that prepared statement constitutes what the documentation calls "a grivous error" (if we presume that a superfluous call to finalize constitutes "use"; and why would we not?).



Fortunately there is no reason ever to want to do this. So, quite simply, don't! If your design is such that you've lost control of your code flow and, at the point of finalize, for some reason have insufficient information about your program's context to know whether the prepared statement has already been finalized, that's fine: much like we do with pointers, you can set it to nullptr so that subsequent calls are no-ops. But if you need to do this, you really should also revisit your design.



Why did it appear to work for you? Pure chance, much like with any other undefined behaviours:




Any use of a prepared statement after it has been finalized can result in undefined and undesirable behavior such as segfaults and heap corruption.




See also: "Why can't I close my car door twice without opening it?" and "Why can't I shave my imaginary beard?"






share|improve this answer













Though the documentation doesn't feel the need to state this explicitly, it's fairly obvious that what you're doing is "undefined behaviour" (within the scope of the library).



Much like deleteing dynamically allocated memory, you are supposed to finalize once. Not twice, not five times, but once. After you've finalized a prepared statement, it has been "deleted" and no longer exists. Any further operations on that prepared statement constitutes what the documentation calls "a grivous error" (if we presume that a superfluous call to finalize constitutes "use"; and why would we not?).



Fortunately there is no reason ever to want to do this. So, quite simply, don't! If your design is such that you've lost control of your code flow and, at the point of finalize, for some reason have insufficient information about your program's context to know whether the prepared statement has already been finalized, that's fine: much like we do with pointers, you can set it to nullptr so that subsequent calls are no-ops. But if you need to do this, you really should also revisit your design.



Why did it appear to work for you? Pure chance, much like with any other undefined behaviours:




Any use of a prepared statement after it has been finalized can result in undefined and undesirable behavior such as segfaults and heap corruption.




See also: "Why can't I close my car door twice without opening it?" and "Why can't I shave my imaginary beard?"







share|improve this answer












share|improve this answer



share|improve this answer










answered Nov 20 '18 at 11:06









Lightness Races in OrbitLightness Races in Orbit

287k51466791




287k51466791













  • Thank you all for the answers. It is obvious that i will redesign the code in order to remove this consecutive invocation of finalize. The reason of the question was to understand the problem clearly, which was achieved. Thanks again.

    – Георги Няголов
    Nov 20 '18 at 12:15



















  • Thank you all for the answers. It is obvious that i will redesign the code in order to remove this consecutive invocation of finalize. The reason of the question was to understand the problem clearly, which was achieved. Thanks again.

    – Георги Няголов
    Nov 20 '18 at 12:15

















Thank you all for the answers. It is obvious that i will redesign the code in order to remove this consecutive invocation of finalize. The reason of the question was to understand the problem clearly, which was achieved. Thanks again.

– Георги Няголов
Nov 20 '18 at 12:15





Thank you all for the answers. It is obvious that i will redesign the code in order to remove this consecutive invocation of finalize. The reason of the question was to understand the problem clearly, which was achieved. Thanks again.

– Георги Няголов
Nov 20 '18 at 12:15


















draft saved

draft discarded




















































Thanks for contributing an answer to Stack Overflow!


  • Please be sure to answer the question. Provide details and share your research!

But avoid



  • Asking for help, clarification, or responding to other answers.

  • Making statements based on opinion; back them up with references or personal experience.


To learn more, see our tips on writing great answers.




draft saved


draft discarded














StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53390865%2fsqlite-consecutive-invocation-of-finalize%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown





















































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown

































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown







Popular posts from this blog

Can a sorcerer learn a 5th-level spell early by creating spell slots using the Font of Magic feature?

Does disintegrating a polymorphed enemy still kill it after the 2018 errata?

A Topological Invariant for $pi_3(U(n))$