‘s’ term in WP_Query extended class causes huge memory leak (268MB)

I’m not sure what convention is with pre_get_posts, but it seems to be for setting additional arguments and not replacing then running the query. Comparing wp_query and my own geo query, I noticed my own had post data in the query object. This may have been what caused the memory leak, but it must have had an infinite loop – my entire DB is no where near 268MB. Perhaps the query is not meant to take place inside the constructor? I’d love to know of a solution using pre_get_posts.

Instead of using pre_get_posts, I used the woocommerce_before_shop_loop hook to replace $wp_query altogether.

add_action('woocommerce_before_shop_loop', 'wr_product_geo_query');
function wr_product_geo_query() {
  global $wp_query;

  if ($wp_query->is_search() && isset($_REQUEST['loc'])) {
    $args = array(
      'post_type'       => $_REQUEST['post_type'] ,
      'posts_per_page'  => 20,
      'fields'          => 'all',
      'lat'             => $_REQUEST['lat'],
      'lng'             => $_REQUEST['lng'],
      'distance'        => $_REQUEST['dist'],
      's' => $_REQUEST['s']
    );

    $wp_query = new WP_Query_Geo( $args );
  }
}

Pretty simple, but I’d like a solution that inserts itself into default search behaviour instead of relying on a template hook.

Update: After much internal deliberation, I believe pre_get_posts is exclusively for modifying an existing query. I’m not modifying it, I’m nuking it. In which case, creating a new query object via a custom template or template hook is the “proper” way to do it.