In the gtk_dialog_run documentation there is a note
After gtk_dialog_run() returns, you are responsible for hiding or destroying the dialog if you wish to do so. 
So the dialog should not get destroyed automaticaly, the programmer must do it.
EDIT:
The another problem is that you are not running GTK main loop (gtk_main() or its variant) so the GTK can not deal with events necessary to destroy a widget (no part of GTK is running in the time the events are present). The sollution for this is in answer to another question using gtk_idle_add() to invoke function after gtk_main()
is called. In this function the dialog is shown, the result is given to the caller, the dialog is destroyed and gtk_main_quit() is called to terminate GTK main loop.
However, gtk_idle_add() is deprecated in GTK+2.6 and is not present in GTK+3.0, so g_idle_add() should be used instead. Your code could be somethink like
struct fch_result {
    gint response;
    // other information to return like filename,...
};
static gboolean fch_dialog(gpointer user_data)
{
    struct fch_result *result = (struct fch_result *) user_data;
    GtkWidget *dialog = gtk_file_chooser_dialog_new ( ... );
    result->response = gtk_dialog_run (GTK_DIALOG(dialog));
    // now add other information to result
    gtk_widget_destroy(dialog);
    gtk_main_quit();  // terminate the gtk_main loop called from caller
    return FALSE;
}
int main(int argc, char** argv)
{
    gtk_init(&argc, &argv);
    struct fch_result data;
    g_idle_add(fch_dialog, &data);
    gtk_main();
    // continue with the program
    return 0;
}