Skip to content

Instantly share code, notes, and snippets.

@alexpreynolds
Last active October 26, 2020 19:48
Show Gist options
  • Save alexpreynolds/92ae97a55154baaccac1b95719282bc9 to your computer and use it in GitHub Desktop.
Save alexpreynolds/92ae97a55154baaccac1b95719282bc9 to your computer and use it in GitHub Desktop.
Growing a C++ vector until a resize triggers a bad_alloc exception
/*
File autogenerated by gengetopt version 2.22.1
generated with the following command:
gengetopt --file-name=cmdoptions
The developers of gengetopt consider the fixed text that goes in all
gengetopt output files to be in the public domain:
we make no copyright claims on it.
*/
/* If we use autoconf. */
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "getopt.h"
#include "cmdoptions.h"
const char *gengetopt_args_info_purpose = "";
const char *gengetopt_args_info_usage = "Usage: vectorTest --output=filename [--help]";
const char *gengetopt_args_info_description = "This application tests the memory limits of the STL vector class on our grid \nengine\n";
const char *gengetopt_args_info_help[] = {
" -h, --help Print help and exit",
" -V, --version Print version and exit",
" -o, --output=filename output for memory allocation results",
0
};
typedef enum {ARG_NO
, ARG_STRING
} cmdline_parser_arg_type;
static
void clear_given (struct gengetopt_args_info *args_info);
static
void clear_args (struct gengetopt_args_info *args_info);
static int
cmdline_parser_internal (int argc, char * const *argv, struct gengetopt_args_info *args_info,
struct cmdline_parser_params *params, const char *additional_error);
static int
cmdline_parser_required2 (struct gengetopt_args_info *args_info, const char *prog_name, const char *additional_error);
static char *
gengetopt_strdup (const char *s);
static
void clear_given (struct gengetopt_args_info *args_info)
{
args_info->help_given = 0 ;
args_info->version_given = 0 ;
args_info->output_given = 0 ;
}
static
void clear_args (struct gengetopt_args_info *args_info)
{
args_info->output_arg = NULL;
args_info->output_orig = NULL;
}
static
void init_args_info(struct gengetopt_args_info *args_info)
{
args_info->help_help = gengetopt_args_info_help[0] ;
args_info->version_help = gengetopt_args_info_help[1] ;
args_info->output_help = gengetopt_args_info_help[2] ;
}
void
cmdline_parser_print_version (void)
{
printf ("%s %s\n", CMDLINE_PARSER_PACKAGE, CMDLINE_PARSER_VERSION);
}
static void print_help_common(void) {
cmdline_parser_print_version ();
if (strlen(gengetopt_args_info_purpose) > 0)
printf("\n%s\n", gengetopt_args_info_purpose);
if (strlen(gengetopt_args_info_usage) > 0)
printf("\n%s\n", gengetopt_args_info_usage);
printf("\n");
if (strlen(gengetopt_args_info_description) > 0)
printf("%s\n\n", gengetopt_args_info_description);
}
void
cmdline_parser_print_help (void)
{
int i = 0;
print_help_common();
while (gengetopt_args_info_help[i])
printf("%s\n", gengetopt_args_info_help[i++]);
}
void
cmdline_parser_init (struct gengetopt_args_info *args_info)
{
clear_given (args_info);
clear_args (args_info);
init_args_info (args_info);
}
void
cmdline_parser_params_init(struct cmdline_parser_params *params)
{
if (params)
{
params->override = 0;
params->initialize = 1;
params->check_required = 1;
params->check_ambiguity = 0;
params->print_errors = 1;
}
}
struct cmdline_parser_params *
cmdline_parser_params_create(void)
{
struct cmdline_parser_params *params =
(struct cmdline_parser_params *)malloc(sizeof(struct cmdline_parser_params));
cmdline_parser_params_init(params);
return params;
}
static void
free_string_field (char **s)
{
if (*s)
{
free (*s);
*s = 0;
}
}
static void
cmdline_parser_release (struct gengetopt_args_info *args_info)
{
free_string_field (&(args_info->output_arg));
free_string_field (&(args_info->output_orig));
clear_given (args_info);
}
static void
write_into_file(FILE *outfile, const char *opt, const char *arg, char *values[])
{
if (arg) {
fprintf(outfile, "%s=\"%s\"\n", opt, arg);
} else {
fprintf(outfile, "%s\n", opt);
}
}
int
cmdline_parser_dump(FILE *outfile, struct gengetopt_args_info *args_info)
{
int i = 0;
if (!outfile)
{
fprintf (stderr, "%s: cannot dump options to stream\n", CMDLINE_PARSER_PACKAGE);
return EXIT_FAILURE;
}
if (args_info->help_given)
write_into_file(outfile, "help", 0, 0 );
if (args_info->version_given)
write_into_file(outfile, "version", 0, 0 );
if (args_info->output_given)
write_into_file(outfile, "output", args_info->output_orig, 0);
i = EXIT_SUCCESS;
return i;
}
int
cmdline_parser_file_save(const char *filename, struct gengetopt_args_info *args_info)
{
FILE *outfile;
int i = 0;
outfile = fopen(filename, "w");
if (!outfile)
{
fprintf (stderr, "%s: cannot open file for writing: %s\n", CMDLINE_PARSER_PACKAGE, filename);
return EXIT_FAILURE;
}
i = cmdline_parser_dump(outfile, args_info);
fclose (outfile);
return i;
}
void
cmdline_parser_free (struct gengetopt_args_info *args_info)
{
cmdline_parser_release (args_info);
}
/** @brief replacement of strdup, which is not standard */
char *
gengetopt_strdup (const char *s)
{
char *result = NULL;
if (!s)
return result;
result = (char*)malloc(strlen(s) + 1);
if (result == (char*)0)
return (char*)0;
strcpy(result, s);
return result;
}
int
cmdline_parser (int argc, char * const *argv, struct gengetopt_args_info *args_info)
{
return cmdline_parser2 (argc, argv, args_info, 0, 1, 1);
}
int
cmdline_parser_ext (int argc, char * const *argv, struct gengetopt_args_info *args_info,
struct cmdline_parser_params *params)
{
int result;
result = cmdline_parser_internal (argc, argv, args_info, params, NULL);
if (result == EXIT_FAILURE)
{
cmdline_parser_free (args_info);
exit (EXIT_FAILURE);
}
return result;
}
int
cmdline_parser2 (int argc, char * const *argv, struct gengetopt_args_info *args_info, int override, int initialize, int check_required)
{
int result;
struct cmdline_parser_params params;
params.override = override;
params.initialize = initialize;
params.check_required = check_required;
params.check_ambiguity = 0;
params.print_errors = 1;
result = cmdline_parser_internal (argc, argv, args_info, &params, NULL);
if (result == EXIT_FAILURE)
{
cmdline_parser_free (args_info);
exit (EXIT_FAILURE);
}
return result;
}
int
cmdline_parser_required (struct gengetopt_args_info *args_info, const char *prog_name)
{
int result = EXIT_SUCCESS;
if (cmdline_parser_required2(args_info, prog_name, NULL) > 0)
result = EXIT_FAILURE;
if (result == EXIT_FAILURE)
{
cmdline_parser_free (args_info);
exit (EXIT_FAILURE);
}
return result;
}
int
cmdline_parser_required2 (struct gengetopt_args_info *args_info, const char *prog_name, const char *additional_error)
{
int error = 0;
/* checks for required options */
if (! args_info->output_given)
{
fprintf (stderr, "%s: '--output' ('-o') option required%s\n", prog_name, (additional_error ? additional_error : ""));
error = 1;
}
/* checks for dependences among options */
return error;
}
static char *package_name = 0;
/**
* @brief updates an option
* @param field the generic pointer to the field to update
* @param orig_field the pointer to the orig field
* @param field_given the pointer to the number of occurrence of this option
* @param prev_given the pointer to the number of occurrence already seen
* @param value the argument for this option (if null no arg was specified)
* @param possible_values the possible values for this option (if specified)
* @param default_value the default value (in case the option only accepts fixed values)
* @param arg_type the type of this option
* @param check_ambiguity @see cmdline_parser_params.check_ambiguity
* @param override @see cmdline_parser_params.override
* @param no_free whether to free a possible previous value
* @param multiple_option whether this is a multiple option
* @param long_opt the corresponding long option
* @param short_opt the corresponding short option (or '-' if none)
* @param additional_error possible further error specification
*/
static
int update_arg(void *field, char **orig_field,
unsigned int *field_given, unsigned int *prev_given,
char *value, char *possible_values[], const char *default_value,
cmdline_parser_arg_type arg_type,
int check_ambiguity, int override,
int no_free, int multiple_option,
const char *long_opt, char short_opt,
const char *additional_error)
{
char *stop_char = 0;
const char *val = value;
int found;
char **string_field;
stop_char = 0;
found = 0;
if (!multiple_option && prev_given && (*prev_given || (check_ambiguity && *field_given)))
{
if (short_opt != '-')
fprintf (stderr, "%s: `--%s' (`-%c') option given more than once%s\n",
package_name, long_opt, short_opt,
(additional_error ? additional_error : ""));
else
fprintf (stderr, "%s: `--%s' option given more than once%s\n",
package_name, long_opt,
(additional_error ? additional_error : ""));
return 1; /* failure */
}
if (field_given && *field_given && ! override)
return 0;
if (prev_given)
(*prev_given)++;
if (field_given)
(*field_given)++;
if (possible_values)
val = possible_values[found];
switch(arg_type) {
case ARG_STRING:
if (val) {
string_field = (char **)field;
if (!no_free && *string_field)
free (*string_field); /* free previous string */
*string_field = gengetopt_strdup (val);
}
break;
default:
break;
};
/* store the original value */
switch(arg_type) {
case ARG_NO:
break;
default:
if (value && orig_field) {
if (no_free) {
*orig_field = value;
} else {
if (*orig_field)
free (*orig_field); /* free previous string */
*orig_field = gengetopt_strdup (value);
}
}
};
return 0; /* OK */
}
int
cmdline_parser_internal (int argc, char * const *argv, struct gengetopt_args_info *args_info,
struct cmdline_parser_params *params, const char *additional_error)
{
int c; /* Character of the parsed option. */
int error = 0;
struct gengetopt_args_info local_args_info;
int override;
int initialize;
int check_required;
int check_ambiguity;
package_name = argv[0];
override = params->override;
initialize = params->initialize;
check_required = params->check_required;
check_ambiguity = params->check_ambiguity;
if (initialize)
cmdline_parser_init (args_info);
cmdline_parser_init (&local_args_info);
optarg = 0;
optind = 0;
opterr = params->print_errors;
optopt = '?';
while (1)
{
int option_index = 0;
static struct option long_options[] = {
{ "help", 0, NULL, 'h' },
{ "version", 0, NULL, 'V' },
{ "output", 1, NULL, 'o' },
{ NULL, 0, NULL, 0 }
};
c = getopt_long (argc, argv, "hVo:", long_options, &option_index);
if (c == -1) break; /* Exit from `while (1)' loop. */
switch (c)
{
case 'h': /* Print help and exit. */
cmdline_parser_print_help ();
cmdline_parser_free (&local_args_info);
exit (EXIT_SUCCESS);
case 'V': /* Print version and exit. */
cmdline_parser_print_version ();
cmdline_parser_free (&local_args_info);
exit (EXIT_SUCCESS);
case 'o': /* output for memory allocation results. */
if (update_arg( (void *)&(args_info->output_arg),
&(args_info->output_orig), &(args_info->output_given),
&(local_args_info.output_given), optarg, 0, 0, ARG_STRING,
check_ambiguity, override, 0, 0,
"output", 'o',
additional_error))
goto failure;
break;
case 0: /* Long option with no short option */
case '?': /* Invalid option. */
/* `getopt_long' already printed an error message. */
goto failure;
default: /* bug: option not considered. */
fprintf (stderr, "%s: option unknown: %c%s\n", CMDLINE_PARSER_PACKAGE, c, (additional_error ? additional_error : ""));
abort ();
} /* switch */
} /* while */
if (check_required)
{
error += cmdline_parser_required2 (args_info, argv[0], additional_error);
}
cmdline_parser_release (&local_args_info);
if ( error )
return (EXIT_FAILURE);
return 0;
failure:
cmdline_parser_release (&local_args_info);
return (EXIT_FAILURE);
}
/** @file cmdoptions.h
* @brief The header file for the command line option parser
* generated by GNU Gengetopt version 2.22.1
* http://www.gnu.org/software/gengetopt.
* DO NOT modify this file, since it can be overwritten
* @author GNU Gengetopt by Lorenzo Bettini */
#ifndef CMDOPTIONS_H
#define CMDOPTIONS_H
/* If we use autoconf. */
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <stdio.h> /* for FILE */
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
#ifndef CMDLINE_PARSER_PACKAGE
/** @brief the program name */
#define CMDLINE_PARSER_PACKAGE "vectorTest"
#endif
#ifndef CMDLINE_PARSER_VERSION
/** @brief the program version */
#define CMDLINE_PARSER_VERSION "1.0"
#endif
/** @brief Where the command line options are stored */
struct gengetopt_args_info
{
const char *help_help; /**< @brief Print help and exit help description. */
const char *version_help; /**< @brief Print version and exit help description. */
char * output_arg; /**< @brief output for memory allocation results. */
char * output_orig; /**< @brief output for memory allocation results original value given at command line. */
const char *output_help; /**< @brief output for memory allocation results help description. */
unsigned int help_given ; /**< @brief Whether help was given. */
unsigned int version_given ; /**< @brief Whether version was given. */
unsigned int output_given ; /**< @brief Whether output was given. */
} ;
/** @brief The additional parameters to pass to parser functions */
struct cmdline_parser_params
{
int override; /**< @brief whether to override possibly already present options (default 0) */
int initialize; /**< @brief whether to initialize the option structure gengetopt_args_info (default 1) */
int check_required; /**< @brief whether to check that all required options were provided (default 1) */
int check_ambiguity; /**< @brief whether to check for options already specified in the option structure gengetopt_args_info (default 0) */
int print_errors; /**< @brief whether getopt_long should print an error message for a bad option (default 1) */
} ;
/** @brief the purpose string of the program */
extern const char *gengetopt_args_info_purpose;
/** @brief the usage string of the program */
extern const char *gengetopt_args_info_usage;
/** @brief all the lines making the help output */
extern const char *gengetopt_args_info_help[];
/**
* The command line parser
* @param argc the number of command line options
* @param argv the command line options
* @param args_info the structure where option information will be stored
* @return 0 if everything went fine, NON 0 if an error took place
*/
int cmdline_parser (int argc, char * const *argv,
struct gengetopt_args_info *args_info);
/**
* The command line parser (version with additional parameters - deprecated)
* @param argc the number of command line options
* @param argv the command line options
* @param args_info the structure where option information will be stored
* @param override whether to override possibly already present options
* @param initialize whether to initialize the option structure my_args_info
* @param check_required whether to check that all required options were provided
* @return 0 if everything went fine, NON 0 if an error took place
* @deprecated use cmdline_parser_ext() instead
*/
int cmdline_parser2 (int argc, char * const *argv,
struct gengetopt_args_info *args_info,
int override, int initialize, int check_required);
/**
* The command line parser (version with additional parameters)
* @param argc the number of command line options
* @param argv the command line options
* @param args_info the structure where option information will be stored
* @param params additional parameters for the parser
* @return 0 if everything went fine, NON 0 if an error took place
*/
int cmdline_parser_ext (int argc, char * const *argv,
struct gengetopt_args_info *args_info,
struct cmdline_parser_params *params);
/**
* Save the contents of the option struct into an already open FILE stream.
* @param outfile the stream where to dump options
* @param args_info the option struct to dump
* @return 0 if everything went fine, NON 0 if an error took place
*/
int cmdline_parser_dump(FILE *outfile,
struct gengetopt_args_info *args_info);
/**
* Save the contents of the option struct into a (text) file.
* This file can be read by the config file parser (if generated by gengetopt)
* @param filename the file where to save
* @param args_info the option struct to save
* @return 0 if everything went fine, NON 0 if an error took place
*/
int cmdline_parser_file_save(const char *filename,
struct gengetopt_args_info *args_info);
/**
* Print the help
*/
void cmdline_parser_print_help(void);
/**
* Print the version
*/
void cmdline_parser_print_version(void);
/**
* Initializes all the fields a cmdline_parser_params structure
* to their default values
* @param params the structure to initialize
*/
void cmdline_parser_params_init(struct cmdline_parser_params *params);
/**
* Allocates dynamically a cmdline_parser_params structure and initializes
* all its fields to their default values
* @return the created and initialized cmdline_parser_params structure
*/
struct cmdline_parser_params *cmdline_parser_params_create(void);
/**
* Initializes the passed gengetopt_args_info structure's fields
* (also set default values for options that have a default)
* @param args_info the structure to initialize
*/
void cmdline_parser_init (struct gengetopt_args_info *args_info);
/**
* Deallocates the string fields of the gengetopt_args_info structure
* (but does not deallocate the structure itself)
* @param args_info the structure to deallocate
*/
void cmdline_parser_free (struct gengetopt_args_info *args_info);
/**
* Checks that all the required options were specified
* @param args_info the structure to check
* @param prog_name the name of the program that will be used to print
* possible errors
* @return
*/
int cmdline_parser_required (struct gengetopt_args_info *args_info,
const char *prog_name);
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* CMDOPTIONS_H */
// main.cpp
#include "cmdoptions.h"
#include <ios>
#include <iostream>
#include <sstream>
#include <fstream>
#include <vector>
#include <string>
#include <new> // std::bad_alloc
using namespace std;
//-------------------------------------------------
// Methods
//-------------------------------------------------
const bool checkArgsInfo (const gengetopt_args_info& args_info)
{
if (! args_info.output_given ) return false;
return true;
}
const bool writeOutput(const std::string line, const std::string of)
{
ofstream ofs;
ofs.open(of.c_str(), ios::app); // append!
if (! ofs.is_open())
{
cout << " Could not open: " << of << endl;
ofs.close();
return false;
}
else
{
ofs.write(line.c_str(), line.size());
ofs.close();
}
return true;
}
template <class T>
const std::string stringify(T x)
{
std::ostringstream o;
o << x;
return o.str();
}
const bool backupOutputFile(const std::string of)
{
const string newOf = of + ".backup";
bool ofExists = false;
ifstream ifs;
ofstream ofs;
// touch file (if it doesn't already exist)
ifs.open(of.c_str(), ios::in);
if (! ifs.is_open())
{
ofs.open(of.c_str(), ios::out);
if (! ofs.is_open())
{
cout << " Could not touch: " << of << endl;
ofs.close();
ifs.close();
return false;
}
else
{
cout << " File: " << of << " touched" << endl;
ofs.close();
ifs.close();
return true;
}
}
else
{
cout << " File: " << of << " exists" << endl;
ifs.close();
ofExists = true;
}
// rename file
if (ofExists)
{
ifs.open(of.c_str(), ios::in);
if (! ifs.is_open())
{
cout << " Could not open: " << of << endl;
ifs.close();
return false;
}
else
{
ifs.close();
if ( rename(of.c_str(), newOf.c_str()) != 0 )
{
cout << " Could not rename: " << of << endl;
return false;
}
else
{
cout << " File: " << of << " renamed to: " << newOf << endl;
}
}
}
// touch file
ifs.open(of.c_str(), ios::in);
if (! ifs.is_open())
{
ofs.open(of.c_str(), ios::out);
if (! ofs.is_open())
{
cout << " Could not touch: " << of << endl;
ofs.close();
ifs.close();
return false;
}
else
{
cout << " File: " << of << " touched" << endl;
ofs.close();
ifs.close();
return true;
}
}
}
template <class T>
const unsigned long totalMemory(const vector<T>& v)
{
return sizeof(v) + sizeof(T) * v.capacity();
}
//-------------------------------------------------
// Main
//-------------------------------------------------
int main (int argc, char** argv)
{
// process command line options
gengetopt_args_info args_info;
if (cmdline_parser (argc, argv, &args_info) != 0) { cout << "cmdline_parser() failed!" << endl; return EXIT_FAILURE; }
if (! checkArgsInfo(args_info)) { cout << "checkArgsInfo() failed!" << endl; return EXIT_FAILURE; }
// check if output file exists
if (! backupOutputFile(args_info.output_arg)) return EXIT_FAILURE;
// instantiate variables
vector<double> testVector;
unsigned long int counter;
string outputString;
const double testValue = 0.0;
const unsigned int sizeofDouble = sizeof(double);
outputString = stringify("Sizeof(double):\t\t\t\t\t") + stringify(sizeofDouble) + stringify(" bytes\n");
outputString += stringify("Sizeof(vector<double>):\t\t\t\t") + stringify(sizeof(testVector)) + stringify(" bytes\n");
for (counter = 0; counter < ULONG_MAX; counter++)
{
try
{
testVector.push_back(testValue);
}
catch (bad_alloc exc)
{
outputString += stringify("Exception:\t\t\t\t\t") + exc.what();
outputString += stringify("\nCounter at which testVector.push_back() failed:\t") + stringify(counter) + stringify("\n");
break;
}
catch (...)
{
outputString += stringify("Exception:\t\t\t\t\tOther");
outputString += stringify("\nCounter at which testVector.push_back() failed:\t") + stringify(counter) + stringify("\n");
break;
}
}
outputString += stringify("Sizeof(testVector):\t\t\t\t") + stringify(totalMemory(testVector)) + stringify(" bytes\n");
cout << outputString;
testVector.clear();
if (! writeOutput(outputString, args_info.output_arg)) return EXIT_FAILURE;
return EXIT_SUCCESS;
}
32BIT_ARCH=-m32
64BIT_ARCH=-m64
32_CFLAGS=${32BIT_ARCH}
32_CXXFLAGS=${32_CFLAGS}
64_CFLAGS=${64BIT_ARCH}
64_CXXFLAGS=${64_CFLAGS}
CXXCOMPILER=g++
CCOMPILER=gcc
32BIT_BINARY_NAME=vectorTest32
64BIT_BINARY_NAME=vectorTest64
all: ${32BIT_BINARY_NAME} ${64BIT_BINARY_NAME}
vectorTest32: main32.o cmdoptions32.o
${CXXCOMPILER} ${32_CXXFLAGS} main32.o cmdoptions32.o -o ${32BIT_BINARY_NAME}
vectorTest64: main64.o cmdoptions64.o
${CXXCOMPILER} ${64_CXXFLAGS} main64.o cmdoptions64.o -o ${64BIT_BINARY_NAME}
main32.o: main.cpp cmdoptions.h
${CXXCOMPILER} ${32_CXXFLAGS} -c main.cpp -o main32.o
main64.o: main.cpp cmdoptions.h
${CXXCOMPILER} ${64_CXXFLAGS} -c main.cpp -o main64.o
cmdoptions32.o: cmdoptions.c cmdoptions.h
${CCOMPILER} ${32_CFLAGS} -c cmdoptions.c -o cmdoptions32.o
cmdoptions64.o: cmdoptions.c cmdoptions.h
${CCOMPILER} ${64_CFLAGS} -c cmdoptions.c -o cmdoptions64.o
clean:
-rm *.o *~ ${32BIT_BINARY_NAME} ${64BIT_BINARY_NAME}
install:
cp ${32BIT_BINARY_NAME} ${64BIT_BINARY_NAME} ../bin
@alexpreynolds
Copy link
Author

alexpreynolds commented Oct 26, 2020

$ srun --mem-per-cpu=1000 --pty bash
...
$ make vectorTest64
$ ./vectorTest64 -o foo
   File: foo touched
srun: Exceeded job memory limit
srun: Job step aborted: Waiting up to 32 seconds for job step to finish.
srun: error: hpcA12: task 0: Killed
...
$ sacct --format="JobID,JobName%80,State,CPUTime,MaxRSS" -j ${JOB_ID}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment